2013-05-09 3 views
5

EDIT: Это не ошибка, только я не знаю о dependent name lookups in templated base classes (который MSVC «помогает» разрешает без ошибок).Это ошибка в GCC?


Я написал реализацию functor некоторое время назад и простую оболочку «Событие», которая ее использует. Он компилируется под MSVC, но GCC дает ошибку об переменной-члене в базовом классе, subscribers, не объявляется; изменение subscribers до this->subscribers решает проблему (!). Похоже, что это происходит только с любопытно повторяющимся шаблоном шаблона и с частичной специализией шаблонов.

Упрощенный источник (извините за галлюциногенный использование шаблона ...):

#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; 
} 

Могу ли я ссылаться неопределенное поведение где-нибудь? Является ли мой синтаксис некорректным? Это действительно ошибка в GCC? Возможно, это известная ошибка? Любое понимание будет оценено!

Подробнее: Скомпилировано с использованием g++ -std=c++11 main.cpp. Я использую GCC версии 4.7.2. Точное сообщение об ошибке:

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

Я тоже столкнулся с этим. Как правило, если он включает в себя шаблоны, всегда доверяйте gcc через msvc (я считаю, что gcc имеет право 99,9 процента времени). –

+0

@JesseGood Еще один дубликат [SO question] (http://stackoverflow.com/q/11405/819272) от еще одного беженца из MSVC. По-видимому, gcc исправил его где-то в версии 3.4, сломав в этом старый код. Но эй, кто сказал, что поставщикам нужна ошибка в качестве точки продажи? – TemplateRex

ответ

8

Это ошибка в MSVC вместо. Имена из зависимых базовых классов должны быть «thisambiguated».

Причина в том, что неквалифицированный поиск зависимых имен proceeds in two phases. На первом этапе базовый класс еще не известен, и компилятор не может разрешить имя. MSVC не выполняет поиск двухфазного имени и задерживает поиск до второй фазы.

Полная специализация

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

не страдает от этой проблемы, потому что оба класса и его база являются регулярные занятия, а не шаблоны классов, и нет зависимости шаблона, чтобы начать с.

При портировании C++ код из MSVC к GCC/Clang, зависимое имя поиска неоднозначности и template keyword disambiguation (шаблон т.е. вызова функции члена с помощью ::template, ->template или .template синтаксис) являются два тонкостей, которые вам приходится иметь дело с (empty base optimization является Еще один). Для всех риторики соответствия стандартам это, вероятно, никогда не будет исправлено по соображениям обратной совместимости.

+1

Не могли бы вы объяснить дальше? Почему в последнем случае это не ошибка? (Nice pun btw.) – Cameron

+1

@Cameron: Последний случай не шаблон, это полная специализация. Все об этом известно во время компиляции. –

+3

@Cameron Часто задаваемые вопросы по C++ содержат [объяснение] (http://www.parashift.com/c++-faq-lite/nondependent-name-lookup-members.html), почему 'this->' требуется в этом случае , Он работает на MSVC, потому что он не реализует поиск двухфазных имен для шаблонов. – Praetorian

Смежные вопросы