2013-05-09 18 views
5

EDIT: To nie jest błąd, tylko ja nie wiem o dependent name lookups in templated base classes (które MSVC "pomocnie" rozwiązuje bez błędów).Czy to błąd w GCC?


Napisałem kiedyś implementację funktora i prostą paczkę "Event", która jej używa. Kompiluje się dobrze pod MSVC, ale GCC podaje błąd dotyczący zmiennej składowej w klasie bazowej, subscribers, bez deklaracji; zmiana subscribers na this->subscribers rozwiązuje problem (!). Wydaje się, że dzieje się tak tylko przy ciekawie powtarzającym się szablonie i przy częściowej specjalizacji szablonu.

uproszczony źródło (przepraszam za użycie szablonu umysłów ...):

#include <vector> 

template<typename TEvent> 
struct EventBase 
{ 
protected: 
     std::vector<int> subscribers; 
}; 

template<typename TArg1 = void, typename TArg2 = void> 
struct Event : public EventBase<Event<TArg1, TArg2> > 
{ 
     void trigger(TArg1 arg1, TArg2 arg2) const 
     { 
       // Error on next line 
       auto it = subscribers.cbegin(); 
     } 
}; 

template<typename TArg1> 
struct Event<TArg1, void> : public EventBase<Event<TArg1> > 
{ 
     void trigger(TArg1 arg1) const 
     { 
       // Using `this` fixes error(?!) 
       auto it = this->subscribers.cbegin(); 
     } 
}; 

template<> 
struct Event<void, void> : public EventBase<Event<> > 
{ 
     void trigger() const 
     { 
       // No error here even without `this`, for some reason! 
       auto it = subscribers.cbegin(); 
     } 
}; 

int main() 
{ 
     return 0; 
} 

jestem powołując niezdefiniowanej zachowanie gdzieś? Czy moja składnia jest w jakiś sposób błędna? Czy to naprawdę błąd w GCC? Czy to może znany błąd? Wszelkie docenianie byłoby docenione!

Więcej szczegółów: Skompilowano przy użyciu g++ -std=c++11 main.cpp. Używam GCC w wersji 4.7.2. Dokładny komunikat o błędzie:

main.cpp: In member function ‘void Event<TArg1, TArg2>::trigger(TArg1, TArg2) const’: 
main.cpp:17:15: error: ‘subscribers’ was not declared in this scope 
+2

Ja też w to wpadłem. Zasadniczo, jeśli dotyczy to szablonów, zawsze ufaj gcc przez msvc (stwierdzam, że gcc ma 99,9% czasu). –

+0

@JesseGood Istnieje nawet duplikat [pytanie SO] (http://stackoverflow.com/q/11405/819272) od jeszcze jednego uchodźcy MSVC. Wygląda na to, że gcc naprawił go gdzieś w wydaniu 3.4, zrywając stary kod. Ale hej, kto powiedział, że sprzedawcy potrzebują kompatybilności z błędami jako punktu sprzedaży? – TemplateRex

Odpowiedz

8

Jest to błąd w MSVC zamiast. Nazwy z bazujących na nich klas bazowych muszą być "zjednoczone".

Powodem jest to, że niewykwalifikowane wyszukiwanie nazw zależnych proceeds in two phases. Podczas pierwszej fazy klasa bazowa nie jest jeszcze znana, a kompilator nie może rozpoznać nazwy. MSVC nie implementuje dwufazowego wyszukiwania nazw i opóźnia wyszukiwanie do drugiej fazy.

Pełna specjalizacja

template<> 
struct Event<void, void> : public EventBase<Event<> > 
{ 
     void trigger() const 
     { 
       // No error here even without `this`, for some reason! 
       auto it = subscribers.cbegin(); 
     } 
}; 

nie cierpi z tego problemu, ponieważ zarówno klasy i jego podstawa są regularne ćwiczenia, a nie szablonów klas, a nie zależność szablon na początku.

przy przenoszeniu kodu C++ z MSVC do gcc/Clang, zależnej nazwa odnośnika dezambiguacji i template keyword disambiguation (szablon czyli wywołanie funkcji członka używając ::template, ->template lub .template składni) są dwa subtelności, że masz do czynienia z (empty base optimization jest inny). W przypadku retoryki przestrzegania standardów prawdopodobnie nigdy nie zostanie to naprawione ze względu na kompatybilność wsteczną.

+1

Czy możesz wyjaśnić dalej? Dlaczego nie jest to błąd w ostatnim przypadku? (Nice pun btw.) – Cameron

+1

@Cameron: Ostatni przypadek nie jest szablonem, to pełna specjalizacja. Wszystko na ten temat jest znane podczas kompilacji. –

+3

@Cameron The C++ FAQ ma [wyjaśnienie] (http://www.parashift.com/c++-faq-lite/nondependent-name-lookup-members.html), dlaczego 'to->' jest wymagane w tym przypadku . Działa na MSVC, ponieważ nie implementuje dwufazowego wyszukiwania nazw dla szablonów. – Praetorian