4
template<typename T>
struct A {
    using U = typename T::U;
    using V = typename T::V; //X
};

struct B {
    using U = int;
    void f() { A<B> a; }   //1
    //A<B> a;              //2
    using V = int;
};

这在当前的 GCC、Clang、MSVC 和 ICC(https://godbolt.org/z/dvExbxszn)上编译。

我想知道这是否实际上指定在标准中工作。A<B>具体来说,允许B::UB::V被查找的实例化点在哪里?

如果我们使用//2而不是//1,所有四个编译器都会拒绝代码,但如果//X被删除则接受。对于这种情况,我理解严格阅读标准可能会使程序格式错误,即使//X被删除,因为实例化点应该高于B. 然而,按照CWG 287中的建议更改,编译器允许查找A::U在需要实例化的点之前声明的A<B>.

但是,需要从完整的类上下文中进行实例化,在void f() { A<B> a; }我看来,编译器假定实例化点在 的定义之后B,因此其中的所有名称B都可用于在实例化中查找。这实际上是在标准中指定的,还是类似于 CWG 287 的情况,编译器试图使实例化的行为类似于非模板定义,反对对标准的严格解释?

4

0 回答 0