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

时间:2015-10-03 08:29:31

标签: c++ templates g++ clang++

我偶然发现g ++(5.2.0)编译了以下内容

template<typename T>
struct A {
    int x;
    struct B {
        void foo() {
            x = 1;
        }
    };
};
如果未使用成员A

即使是A::BB::foo正在发布。即使只是编译no-op语句x,你也可以合理地得到A作为&A<int>::B::foo;的非静态成员的编译错误。

然而,

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

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

2 个答案:

答案 0 :(得分:2)

代码中的x是一个非依赖名称,并且标准呈现的模板无法有效地实例化,无论您提供什么样的模板参数都是错误的,不需要诊断(实际上这也适用于“temploids”,作为标准显示的一个例子。也就是说,规则同样适用于类模板的成员。)

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

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

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

但是,包含类模板的类型称为当前实例化,这意味着它的含义始终保持不变,并且根据模板参数不能更改。因此,模板定义本身可能会因某些用途(如您的用途)而变得格式不正确。

答案 1 :(得分:1)

[temp.res] / 8说:

  

没有诊断   应为可以生成有效专业化的模板颁发。如果没有有效的专业化可以   为模板生成,并且该模板未实例化,模板格式错误,无法诊断   必需的。

我认为第二句适用于B的未使用部分。如果函数未实例化,则编译器不需要意识到它无法实例化。