c++ - 这是 GCC 中的错误吗?

标签 c++ templates visual-c++ gcc name-lookup

编辑:这不是错误,只是我不知道 dependent name lookups in templated base classes (MSVC“有帮助地”解决而没有错误)。


我不久前写了一个仿函数实现,以及一个使用它的简单“事件”包装器。它在 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

最佳答案

这是 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 是另一个)。对于所有标准合规性言论,出于向后兼容性的原因,这可能永远不会得到解决。

关于c++ - 这是 GCC 中的错误吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16471161/

相关文章:

c++ - g++ Double Free 或腐败...但是如何?

c++ - 为什么 GCC 不能将此使用声明解析为正确的类型

c++ - 如何使 Insure++ 与 boost 和 g++ 3.4.x 一起工作

c++ - 我可以在基元上调用 delete 吗?

c++ - 如何在 Eigen 中定义行优先稀疏 vector

c++ - 复制或 constref 一个 shared_ptr?

c++ - 加速字节模式扫描 C++

c++ - 使用外部类的模板参数设置内部模板类的默认模板参数

c++ - 有没有一种简单的方法来对 CObList 进行排序?

Eigen 动态大小矩阵的 C++ 数组