内部类型作为模板参数

时间:2011-11-03 19:57:00

标签: c++ templates

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

2 个答案:

答案 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
}