编辑:这不是一个错误,只是我不知道dependent name lookups in templated base classes(哪个MSVC“有帮助”解决而没有错误。)
我前段时间写了一个functor实现,还有一个使用它的简单“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;
}
我是否在某处调用未定义的行为?我的语法有点错吗?这真的是海湾合作委员会的一个错误吗?它可能是一个已知的bug吗?任何见解都将不胜感激!
更多详细信息:使用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
答案 0 :(得分:9)
这是MSVC中的错误。依赖基类的名称必须是“明显的”。
原因是对从属名称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是另一个)。对于所有符合标准的修辞,由于向后兼容性原因,这可能永远不会得到解决。