内部类型作为模板参数



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;
}

你是正确的,c++ 03不允许使用具有内部链接的类型作为模板类型参数,而c++ 11允许。

我似乎记得,然而,匿名命名空间内的定义仍然具有外部链接。


是的,第3.5节[basic.link]

如果名称是

,则具有命名空间作用域(3.3.5)的名称具有内部链接
  • 显式声明为静态的对象、引用、函数或函数模板,或者
  • 显式声明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]

这不是该规则的有效示例。示例中的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
}

相关内容

最新更新