2016-11-17 5 views
10

Rozważmy następujący program:Funkcja operatora cast kompiluje dobrze w g ++, ale nie w innych kompilatorach. Czemu?

struct S { 
    using T = float; 
    operator T() { return 9.9f; } 
}; 
int main() { 
    S m; 
    S::T t = m; 
    t = m.operator T(); // Is this correct ? 
} 

Program kompiluje grzywny w g ++ (Zobacz na żywo demo here)

Ale to nie w kompilacji w brzękiem ++ MSVC++ & Intel C++ kompilator

dzyń ++ daje następujące błędy (Zobacz demo na żywo here)

main.cpp:8:20: error: unknown type name 'T'; did you mean 'S::T'? 
    t = m.operator T(); // Is this correct ? 
       ^
        S::T 
main.cpp:2:11: note: 'S::T' declared here 
    using T = float; 

MSVC++ daje następujące błędy (Zobacz na żywo demo here)

source_file.cpp(8): error C2833: 'operator T' is not a recognized operator or type 
source_file.cpp(8): error C2059: syntax error: 'newline' 

Intel kompilator C++ odrzuca również ten kod (zob żywo demo here)

Więc pytanie brzmi, który kompilator jest tutaj? Czy tutaj g ++ jest niepoprawny, czy też 3 inne kompilatory są niepoprawne? Co mówi o tym standard C++?

+2

Wow, bardzo ładne pytanie! – Columbo

Odpowiedz

8

[basic.lookup.classref]/7:

Jeżeli ID ekspresja jest konwersji funkcja ID, jego konwersji typu ID najpierw szuka się w klasie ekspresji obiektu a nazwa, jeśli została znaleziona, jest używana. W przeciwnym razie zostanie on sprawdzony w kontekście całego końcowego wyrażenia . W każdym z tych wyszukiwań uwzględniane są tylko nazwy określające typy lub szablony, których specjalizacje są typami. [Przykład:

struct A { }; 
namespace N { 
    struct A { 
    void g() { } 
    template <class T> operator T(); 
    }; 
} 

int main() { 
    N::A a; 
    a.operator A(); // calls N::A::operator N::A 
} 

- przykład koniec]

Wskazuje to na przykład może być w porządku, choć w powyższym przykładzie A uprzednio zostały uznane jako nazwa typu, widoczne do main.

Zostało to omówione w core issue 156, złożony przez całą drogę z powrotem w 1999 roku:

Jak o:

struct A { typedef int T; operator T(); }; 
struct B : A { operator T(); } b; 
void foo() { 
    b.A::operator T(); // 2) error T is not found in the context 
        // of the postfix-expression? 
} 

Czy ta interpretacja jest prawidłowy? Czy też zamiarem było to, aby był to błąd o numerze tylko wtedy, gdy w obu zakresach znaleziono T i odesłano do różnych jednostek ?

Erwin Unruh: Chodziło o to, aby wyglądać w obu kontekstach. Jeśli znajdziesz go tylko raz, jest to symbol. Jeśli znajdziesz je w obu, oba symbole muszą być pod tym względem "takie same". (Jeśli go nie znajdziesz, jest to błąd).

Więc powiedziałbym, że Clang jest źle: intencją wyrażoną w treści do pewnego stopnia, jest to, że możemy znaleźć T, nawet jeśli tylko w klasie.

+0

Zaskakujące ciuchy! –

+0

Powinieneś też powiedzieć, że ICC i MSVC++ również są nieprawidłowe. tylko g ++ ma rację !!! – Destructor

+0

@Destructor Tak, ale Clang w szczególności jest interesujący, ponieważ zazwyczaj ma rację. W ciągu ostatnich 10 lub 20 pytań dotyczących prawników językowych, w których Clang i GCC różniły się pod względem zachowania, Clang miał rację. – Columbo

Powiązane problemy