2016-03-05 3 views
8

Rozważmy następujący fragment oZależnie nazwą odnośnika w matrycy funkcji: szczęk odrzuca gcc przyjmuje

struct X { }; 

namespace foo { 
    template <class T> 
    void bar() { T{} < T{}; } 

    void operator<(const X&, const X&) {} 
} 

int main() { 
    foo::bar<X>(); 
} 

szczęk odrzuca kod gcc akceptuje. Czy jest to błąd gcc, czy jest to błąd clang?

+0

Nie widzę, jak to jest błąd, ponieważ typ 'T' może odnosić się do dowolnego typu. Jeśli ten typ 'T' nie przeładuje ani nie obsłuży operatora' <', wówczas funkcja' bar' zakończy się niepowodzeniem. Ponieważ przeciąłeś operatora '<', wszystko działa dobrze. Domyślam się, że wszystko idzie do tego, w jaki sposób kompilatory czytają kod, ale w sensie semantyki nie jest to podatne na błędy. – Poriferous

+0

@Poriferous To nie ma żadnego sensu. Pytanie brzmi, jakie jest prawidłowe zachowanie 'bar()' dla typów 'T', które nie mają' operatora <'. Prawidłowe zachowanie to: "tak, znajduje' bar :: operator <"(w tym przypadku clang ma błąd) lub" kod jest źle sformułowany "(w tym przypadku gcc ma błąd). – Barry

+0

To nie ma sensu, ponieważ 'bar' jest funkcją i nie ma operatora' '<". Ponieważ zdefiniowałeś 'operator <' dla struktury 'X', naprawdę nie widzę problemu. Nawet jeśli przeciążenie operatora zostało osadzone w strukturze 'X', kod powinien nadal poprawnie się kompilować. Aby być uczciwym, to klang ma błąd, ponieważ wydaje się, że zakłada typ. Mam na myśli, czy próbowałeś zastąpić 'foo :: bar ()' z czymś takim jak 'foo :: bar ()' i sprawdzić, czy klang odrzuca również ten kod? – Poriferous

Odpowiedz

5

GCC jest nieprawidłowy Klang jest poprawny. Fakt, że GCC połknął nieprawidłowy kod jako ten, który pokazałeś, jest również wymieniony na stronie kompatybilności CLANG here.

Nielegalne nazwiska są wyszukiwane w następujący sposób.

  1. Kompilator przeprowadza niewykwalifikowane wyszukiwanie w zakresie, w którym nazwa została zapisana. W przypadku szablonu oznacza to, że wyszukiwanie odbywa się w punkcie, w którym szablon jest zdefiniowany, a nie w miejscu jego utworzenia. Od operator< nie został jeszcze zadeklarowany w tym miejscu, niewykwalifikowane wyszukiwanie go nie znajdzie.
  2. Jeśli nazwa jest wywoływana jak funkcja, to kompilator wykonuje również wyszukiwanie zależne od argumentów (ADL). (Czasami niewykwalifikowane wyszukiwanie może tłumić ADL, zobacz [basic.lookup.argdep] paragraf 3, aby uzyskać więcej informacji.) W ADL kompilator analizuje typy wszystkich argumentów w wywołaniu. Po znalezieniu typu klasy wyszukuje nazwę w przestrzeni nazw tej klasy; wynikiem są wszystkie deklaracje znalezione w tych przestrzeniach nazw oraz deklaracje z niewykwalifikowanego wyszukiwania. Jednak kompilator nie wykonuje ADL, dopóki nie pozna wszystkich typów argumentów.
6

Wierzę, że jest to błąd gcc, złożony jako 70099. W [temp.dep.res]

w nim nazwy zależne nazwy z następujących źródłach uważa:
(1,1) - deklaracji, które są widoczne w punkcie definicji wzoru.
(1.2) - Deklaracje z przestrzeni nazw powiązanych z typami argumentów funkcji zarówno z kontekstu tworzenia instancji (14.6.4.1), jak iz kontekstu definicji.

foo::operator<() nie jest widoczny w punkcie definicji szablonu, a nie jest w przestrzeni nazw związanej z argumentów funkcji (X „s związany nazw jest tylko globalna przestrzeń nazw ::). Więc myślę, że gcc nie ma racji, aby znaleźć foo::operator< i clang jest poprawny, aby odrzucić kod.