2015-05-11 19 views
17

widzę przykład z C++ 11 Standard (n3337, 14.8.2.3/7)Szablon typ argumentu odliczenie przez operatora konwersji

struct A { 
template <class T> operator T***(); 
}; 
A a; 
const int * const * const * p1 = a; // T is deduced as int, not const int 

i spróbować odtworzyć go za pomocą różnych kompilatorów. Zmieniłem przykład trochę dodając oświadczenie z typu T w funkcji konwersji

struct A { 
    template <class T> operator T***() 
    { 
     T t; //if T==const int, then it is error (uninitialized const) 
     return nullptr; 
    } 
}; 
A a; 
const int * const * const * p1 = a; 

int main(){} 

Wszystkie kompilatory (VS2014, gcc 5.1.0 i 3.5.1 dzyń) dają błąd w deklaracji „T” , co oznacza, że ​​T jest wydedukowane jako const int. Dlaczego? Czy to jakieś rozszerzenie? został

+3

Gratulacje, znalazłeś błąd kompilatora. (To nie jest zgodne rozszerzenie: odrzuca kod, który jest dobrze uformowany zgodnie ze standardem.) –

+2

@ T.C. Tylko [zgłaszane] (https://gc.gnu.org/bugzilla/show_bug.cgi?id=66108) to. Szkoda, że ​​bugzilla nie pozwala ci na edycję ninja-edycję! – Barry

+1

Zadziwiająco. Aż 3 kompilatory mają ten sam błąd :) P.S. Kompilatory icc 13.0.1 ok – user3514538

Odpowiedz

9

Ten objęty CWG issue #349, otwarty przez dewelopera EDG C++ front end (który podobno wywodzi int, nie const int):

Wpadliśmy w kwestii dotyczącej kwalifikacji konwersje robiąc szablonu odliczenie argumentu dla funkcji konwersji .

Pytanie brzmi: Jaki jest typ T w funkcjach konwersji nazywany przez ten przykład? Czy T "int" lub "const int"?

Jeśli T jest "int", funkcja konwersji w klasie A działa, a klasa w kończy się niepowodzeniem (ponieważ wyrażenie zwrotne nie może zostać przekonwertowane na typ zwracanej funkcji). Jeśli T jest "const int", A zawiedzie i B działa.

Ponieważ konwersja kwalifikacji jest wykonywana na wyniku funkcji konwersji , nie widzę żadnej korzyści w dedukowaniu T jako const int.

Ponadto, myślę, że kod w klasie A jest bardziej prawdopodobne niż kod w klasie B. Jeśli autor klasy planuje powrocie wskaźnik do const podmiotu, spodziewam funkcję do zostały napisane ze stałą w typie zwracanym.

W związku z tym uważam, że poprawny wynik powinien być taki, że T jest int.

struct A { 
    template <class T> operator T***() { 
     int*** p = 0; 
     return p; 
    } 
}; 

struct B { 
    template <class T> operator T***() { 
     const int*** p = 0; 
     return p; 
    } 
}; 

int main() 
{ 
    A a; 
    const int * const * const * p1 = a; 
    B b; 
    const int * const * const * p2 = b; 
} 

Właśnie wprowadziliśmy tę funkcję, a do czasu wyjaśnienia przez komisję, dedukujemy T jako int. Wygląda na to, że g ++ i kompilator Sun dedukują T jako const int.

tylko ten przyniósł cytowany akapit do istnienia (nie istnieje w C++ 03!) I był przypuszczalnie pomijane przez twórców kompilatora.