使用别名作为作用域获取父成员时的不同编译器行为

Different compiler behaviour when using alias as scope to get parent member

提问人:Johnmph 提问时间:4/25/2020 最后编辑:FedorJohnmph 更新时间:1/3/2022 访问量:63

问:

此代码在 Clang 和 Visual C++ 上编译良好,但在 GCC 上则不然:

#include <iostream>


template <class T>
struct Test {
    Test(T &t) : _t(t) {
    }
    
    void method() {
        std::cout << _t.Internal::_value << "\n";       // Doesn't work on GCC
        std::cout << _t.T::Internal::_value << "\n";    // Work on all compilers
    }

private:
    T &_t;
};

template <class T>
struct Base {
    T _value = 1;
};

template <class T>
struct Child : Base<int> {
    using Internal = Base<int>;
    
    int _value = 2;
};

int main(int argc, const char * argv[]) {
    Child<float> child;
    Test<Child<float>> test(child);
    
    test.method();
    
    return 0;
}

来自 GCC 的错误消息是

error: 'Internal' has not been declared
    9 |         std::cout << _t.Internal::_value << "\n";
      |                         ^~~~~~~~

哪一个是对的?

C++ 模板 继承 -查找 依赖项名称

评论

0赞 M.M 4/25/2020
简化版
0赞 M.M 4/25/2020
我认为它应该有效,因为在实例化上下文中发生了类型相关名称的名称查找(但并不完全确定)

答:

1赞 Fedor 1/3/2022 #1

Visual C++ 和 Clang 接受此代码是正确的。

这是 GCC 中的一个错误,阻止了它做同样的事情。问题中的错误一直到海湾合作委员会 10,在海湾合作委员会 11 中,其措辞改为

error: request for member 'Internal' in non-class type 'T'
    9 |         std::cout << _t.Internal::_value << "\n";
      |                         ^~~~~~~~

GCC 主干最终也接受了代码。演示:https://gcc.godbolt.org/z/dj34Yhns3

因此,我们可以期待 GCC 12 中的修复。