这是GCC中的错误吗? [英] Is this a bug in GCC?

查看:171
本文介绍了这是GCC中的错误吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

This is not a bug, just me not knowing about dependent name lookups in templated base classes (which MSVC "helpfully" resolves without errors).

我写了一个functor实现一个简单的事件使用它。它在MSVC下编译良好,但是GCC给出了一个关于基类中的成员变量的错误, subscribers ,未声明;将订阅者更改为 this-> subscribers 可解决问题(!)。

I wrote a functor implementation a while back, and a simple "Event" wrapper that uses it. It compiles fine under MSVC, but GCC gives an error about a member variable in the base class, subscribers, not being declared; changing subscribers to this->subscribers resolves the issue(!). It appears to happen only with the curiously recurring template pattern, and with partial template specialization.

简化的源代码(对于心灵模糊的模板使用...很抱歉):

Simplified source (sorry for the mind-bending template usage...):

#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的一个错误?这可能是一个已知的错误?

Am I invoking undefined behaviour somewhere? Is my syntax somehow wrong? Is this really a bug in GCC? Is it perhaps a known bug? Any insight would be appreciated!

更多细节:编译使用 g ++ -std = c ++ 11 main.cpp 。我使用GCC版本4.7.2。精确错误消息:

More details: Compiled using g++ -std=c++11 main.cpp. I'm using GCC version 4.7.2. Exact error message:

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


推荐答案

这是MSVC中的错误。来自依赖基类的名称必须消歧。

This is a bug in MSVC instead. Names from dependent base classes have to be "thisambiguated".

原因是对依赖名称的无限制查找 分两期进行 。在第一阶段,基类尚未知晓,编译器无法解析名称。 MSVC不实现两阶段名称查找,并延迟查找直到第二阶段。

The reason is that unqualified lookup of dependent names proceeds in two phases. During the first phase, the base class is not yet known and the compiler cannot resolve the name. MSVC does not implement two-phase name lookup and delays the lookup until the second phase.

完全专业化

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

没有这个问题,因为类和它的基类都是常规类,而不是类模板

does not suffer from this problem, because both the class and its base are regular classes, not class templates, and there is no template dependency to begin with.

当将C ++代码从MSVC移植到gcc / Clang时,依赖名称查询消除歧义,并且 模板关键字消歧(即调用成员函数模板使用 :: template - >模板 .template 语法)处理(空基本优化是另一个)。对于所有的标准合规修辞,这可能永远不会固定的原因向后兼容性。

When porting C++ code from MSVC to gcc/Clang, dependent name lookup disambiguation and the template keyword disambiguation (i.e. calling member function template using ::template, ->template or .template syntax) are two of the subtleties that you have to deal with (empty base optimization is another one). For all the Standards compliance rhetoric, this will probably never be fixed for reasons of backwards compatibility.

这篇关于这是GCC中的错误吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆