考虑这个例子:
class A
{
void foo();
public:
void bar();
};
template <class> class B
{
B()
{
A a;
a.foo(); // 1
A::bar(); // 2
a.bar(1); // 3
}
};
注意B
永远不会被实例化。
clang++
报告所有三条标记的行都是错误的。 g++
(4.8.3)接受行1
和2
,仅报告行3
。
如果B
被实例化,g++
会愉快地将所有三行报告为错误。
这是g++
错误吗?有人会这么认为。 A
不是依赖名称,应在模板定义时正常检查其成员。是否有我看不到的细微差别?
答案 0 :(得分:19)
这些预实例化消息不是由标准强制执行的,而是由编译器决定的
n3337§14.6 - 8
对于a的模板定义,不应发出诊断 可以生成有效的专业化。如果没有有效的专业化可以 为模板定义生成,而该模板不生成 实例化后,模板定义格式不正确,无诊断 必需的。强>
强调我的
答案 1 :(得分:7)
在模板定义时,一般不可能判断a.foo();
或A::bar();
是否为错误,即使是A::foo
和{{1}的特定定义也是如此}。
一般来说,A::bar
可能有效,如果a.foo();
有A
的某些特殊化作为朋友,而不是其他人,这会使有效性依赖于模板参数。
一般来说,如果B<T>
直接或间接地将A::bar();
作为基类,B<T>
可能有效,并且模板类在模板定义时通常不知道它们的基类
即使可以检测到这些都不可能此处(A
没有朋友,A
没有基础),但它需要重大努力,收效甚微。因此,在实例化时间总是执行此类检查是有意义的,这是GCC采取的方法。
在C ++中实际上没有规则要求在模板定义时诊断它(正如Marco A。的答案正确指出的那样)。只有在实例化模板时,模板定义中的任何错误都会导致程序格式错误,需要诊断,每2.2p1子弹点8:
如果任何实例化失败,程序就会格式不正确。
在你的程序中,没有实例化,因此没有实例化失败。