这是GCC中的错误吗?

Cam*_*ron 6 c++ gcc templates visual-c++ name-lookup

编辑:这不是一个错误,只是我不知道模板化基类中的依赖名称查找(MSVC"有帮助"解决没有错误).


我前段时间写了一个functor实现,还有一个使用它的简单"Event"包装器.它在MSVC下编译得很好,但GCC给出了基类中成员变量的错误subscribers,没有被声明; 改变subscribersthis->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;
}
Run Code Online (Sandbox Code Playgroud)

我在某处调用未定义的行为吗?我的语法有点错吗?这真的是海湾合作委员会的一个错误吗?它可能是一个已知的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
Run Code Online (Sandbox Code Playgroud)

Tem*_*Rex 9

这是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();
        }
};
Run Code Online (Sandbox Code Playgroud)

没有遇到这个问题,因为类及其基类都是常规类,而不是类模板,并且没有模板依赖性开始.

当从MSVC移植的C++代码的gcc /铛,从属名称查找歧义和template关键字歧义(即使用调用成员函数模板::template,->template.template语法)是两个,你必须处理微妙的(空基地优化是另一个).对于所有符合标准的修辞,由于向后兼容性的原因,这可能永远不会得到解决.

  • @Cameron C++ FAQ有一个[解释](http://www.parashift.com/c++-faq-lite/nondependent-name-lookup-members.html),为什么在这种情况下需要`this->`.它适用于MSVC,因为它不实现模板的两阶段名称查找. (3认同)