ISO 98/03标准(第14.3.1节)似乎禁止使用具有内部链接的类型作为模板参数。 (参见下面的示例。)C ++ 11标准没有。 G ++ - 使用旧标准 - 允许它。 我误解了03标准,还是g ++只是让这个幻灯片?
namespace
{
struct hidden { };
}
template<typename T>
struct S
{
T t;
};
int main()
{
S<hidden> s;
return 0;
}
答案 0 :(得分:7)
你是正确的,C ++ 03不允许使用具有内部链接的类型作为模板类型参数,而C ++ 11则允许。
然而,我似乎记得,匿名命名空间内的定义仍然具有外部链接。
是的,第3.5节[basic.link]
说
具有命名空间作用域(3.3.5)的名称具有内部链接(如果它是
的名称)
- 明确声明为static的对象,引用,函数或函数模板,
- 显式声明为
const
并且既未明确声明extern
也未声明具有外部链接的对象或引用;或- 匿名工会的数据成员。
具有命名空间作用域的名称具有外部链接(如果它是
的名称)
- 一个对象或参考,除非它有内部联系;或
- 一个功能,除非它有内部联系;或
- 一个命名类(第9节),或在typedef声明中定义的未命名类,其中该类具有用于链接目的的typedef名称(7.1.3);或
- 命名枚举(7.2),或在typedef声明中定义的未命名枚举,其中枚举具有用于链接目的的typedef名称(7.1.3);或
- 属于具有外部链接的枚举的枚举器;或
- 模板,除非它是具有内部链接的功能模板(第14条);或
- 命名空间(7.3),除非它在未命名的命名空间中声明。
在命名空间范围内有一个命名类,它有外部链接。
ISO / IEC 14882:2003第115页底部的脚注澄清了:
虽然未命名的命名空间中的实体可能具有外部链接,但它们实际上由其翻译单元唯一的名称限定,因此永远不会从任何其他翻译单元中看到。
如果您有其他版本,请尝试查看第7.3.1.1节[namespace.unnamed]
答案 1 :(得分:4)
这不是规则的有效示例。示例中的hidden
类具有外部链接。 (它有一个编译器生成的唯一名称,以便当前翻译单元之外的任何内容都不能与它实际链接,但它仍然是外部的。)
该标准给出了一个本地类型的例子:
template <class T> class X { /* ... */ };
void f()
{
struct S { /* ... */ };
X<S> x3; // error: local type used as template-argument
X<S*> x4; // error: pointer to local type used as template-argument
}