如果嵌套类型(未访问)带有无法编译的方法,是否可以实例化模板?

Can a template be instantiated if there is nested type (not accessed) with a method that cannot be compiled?

无意中发现g++(5.2.0)编译如下

template<typename T>
struct A {
    int x;
    struct B {
        void foo() {
            x = 1;
        }
    };
};

甚至实例化 AA::B,前提是不使用成员 B::foo。即使只编译无操作语句 &A<int>::B::foo;.

,你也会合理地得到一个编译错误,因为 xA 的非静态成员

clang (3.6.2) 但是拒绝模板,即使 A 根本没有实例化,因为它说非静态成员名称 x 不能在内部使用 B 而只是阅读模板定义。

这是 g++ 中的错误还是 clang 对未实例化的模板成员过于严格?

[temp.res]/8 说:

No diagnostic shall be issued for a template for which a valid specialization can be generated. If no valid specialization can be generated for a template, and that template is not instantiated, the template is ill-formed, no diagnostic required.

我相信第二句适用于 B 中未使用的部分。如果函数没有被实例化,编译器永远不需要意识到它不能被实例化。

代码中的 x 是一个非依赖名称,标准呈现的模板无法有效实例化,无论您作为模板参数提供的格式是否正确,都不需要诊断(实际上这也适用于 "temploids",如标准中的示例所示。也就是说,规则同样适用于 class 模板的成员)。

您的代码与访问周围 class 名称的任何正常 class 一样无效。请注意,方向在这里很重要。以下 不会 格式错误(因为您 可以 专门化 A<T>::B 这样 x 对于 A<int>::B 是一个静态成员,例如。

template<typename T>
struct A {
    struct B {
       int x;
    };

    void f() {
       B::x = 1;
    }
};

然而,封闭 class模板的类型称为当前实例化,这意味着它的含义始终保持相同,不能根据模板参数更改。因此,模板定义本身可能会因某些用途(例如您的用途)而呈现格式错误。