Это ошибка в GCC?

РЕДАКТИРОВАТЬ: Это не ошибка, просто я не знаю о поиск зависимых имен в шаблонных базовых классах (который MSVC «услужливо» разрешает без ошибок).


Некоторое время назад я написал реализацию функтора и простую оболочку «Event», которая ее использует. Он прекрасно компилируется под 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

6

Решение

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

Причина в том, что неквалифицированный поиск зависимых имен протекает в два этапа. На первом этапе базовый класс еще не известен, и компилятор не может разрешить имя. 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 устранение неоднозначности ключевых слов (то есть вызов шаблона функции-члена с использованием ::template, ->template или же .template синтаксис) две тонкости, с которыми вам приходится иметь дело (оптимизация пустой базы еще один). При всей риторике соответствия стандартам это, вероятно, никогда не будет исправлено из-за обратной совместимости.

9

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]