2015-07-02 12 views
10

Możliwe jest zdefiniowanie i kopia zainicjować zmienną wewnątrz warunku instrukcji if:Direct-inicjalizacji obiektu wewnątrz warunku

if(int i = 17) { ... } 

ta działa również z typów zdefiniowanych przez użytkownika, biorąc pod uwagę, że przeciążenie one operator bool:

if(Foo f = 42)  { ... } 
if(Foo f = Foo(43)) { ... } 

Dlaczego nie mogę korzystać z bezpośredniego inicjalizację, jak poniżej?

if(Foo f(51)) { ... } 

GCC emituje error: expected primary-expression before 'f'.

Live on Coliru

Czy istnieje powód inny niż „ponieważ gramatyka mówi tak”? I jak mogę obejść to?

Pracuję z VC++ 03, gdzie Foo:

  • jest obiektem RAII wrażliwe, dla których Zająłem nie zdefiniować konstruktor kopiujący
  • jest podejmowanie szablon argumenty z użytkownikiem
  • ma konstruktora dwóch parametrów

... więc wolałbym uniknąć kopiując je lub powtarzając jego typ.

Uwaga: Chociaż moim rzeczywistym problemem jest C++ 03, jestem (akademicko) zainteresowany odpowiedziami w C++ 11.

+0

Podobne do [Can zmienna być zdefiniowana tylko w zakresie if-oświadczenie, podobnie jak to często zrobić dla pętli FOR-?] (Http://stackoverflow.com/q/24017216/1708801) –

+0

Dlaczego myślisz, że deklaracja 'Foo f = 42' implikuje kopiowanie/przenoszenie? Nie powinien kopiować elizacji? – Columbo

+0

@Columbo AFAIK skopiować elizja jest optymalizacja że Maus lub nie mogą być wykonane, ale nawet jeśli nie jest to obiekt potrzebuje konstruktor kopiujący, który ja wyłączone, aby uniknąć 'auto_ptr'-jak zła. W końcu rozwiązałem problem, przekazując 'std :: pair'. – Quentin

Odpowiedz

10

W C++ 03, można jedynie użyć składni kopiowaniem inicjalizacji:

wyboru-oświadczenie:
        if (stan)oświadczenie
        [...]

stan:
        ekspresji
        typu specyfikator-nast declarator= przyporządkowanie ekspresja

ponieważ C++ 11 listy- dodano inicjalizację:

stan:
        ekspresji
        atrybut specyfikator-nast opcjonalniedecl-specyfikator-nast declarator=inicjator klauzula
        atrybut specifier-nast optdecl-specifier-nast declarator usztywnione-startowe lista

składni bezpośredniego inicjalizacji, tj Foo f(…), prawdopodobnie uniknięto go z tego samego powodu, dla którego nie był on dozwolony dla niestatycznych inicjatorów danych z danymi: niejasności, w szczególności "najbardziej irytująca analiza".

2

Ponieważ standard C++ 03 pozwala jedynie przyporządkowanie inicjalizacji wewnątrz warunków:

condition: 
    expression 
    type-specifier-seq declarator = assignment-expression 
2

Biorąc pod uwagę swoje ograniczenia, wierzę w C++ 03 jedynym rozwiązaniem jest zadeklarować zmienną poza stwierdzeniem if, dodając szelki dla określania zakresu:

{ 
    Foo f(51, 52); 
    if (f) { 
     //... 
    } 
} 

w C++ 11 można wykorzystać usztywnione inicjalizacji składni:

if (Foo f{51, 52}) { 
    //... 
}