将结构传递给具有外部常量模板.外置是干什么用的

Passing a struct to a template with extern const. What is the extern for?

本文关键字:干什么 常量 结构 外部      更新时间:2023-10-16

我在问自己为什么以下代码有效以及说明符extern在实例化baz_instance时的作用:

struct baz {
    int value;
};
extern const baz baz_instance = {3};
template<baz const& b>
int foo(){
    return b.value;
}
int main(){
    foo<baz_instance>();
    return 1;
}
为什么

上面的代码首先要编译,如果省略extern说明符,为什么它不再编译?在此示例中,extern说明符的作用是什么?

这是标准中从 C++03 更改为 C++11 的部分之一。

在C++03中,[temp.arg.nontype]写道:

类型、非模板模板参数的模板参数应为以下参数之一:

  • [...]
  • [...]
  • 具有外部链接的对象或函数的地址,包括函数模板和函数模板ID,但不包括非静态类成员,表示为&id-expression,其中&是可选的,如果名称引用函数或数组,或者如果相应的模板参数是引用;或
  • [...]

在 C++11 中,由于问题 1155,它得到了更新,尽管 GCC 仍然存在有关此行为的错误:

  • 一个常量表达式 (5.19(,它指定具有静态存储持续时间的完整对象的地址 和外部或内部链接或具有外部或内部链接的功能,包括功能 模板和函数模板 ID,但不包括非静态类成员,表示(忽略括号( as & id-expression,其中 id-expression 是对象或函数的名称,除了 如果名称引用函数或数组,则可以省略,如果相应的 模板参数是一个参考;或

在C++14中,这进一步简化,甚至没有提到链接。

至于您的具体问题,extern说明符将外部链接添加到baz_instance。没有它,baz_instance就有了内部联系。在 C++03 中,需要外部链接才能具有引用类型的非类型模板参数。在 C++11 中,您不再这样做 - 因此不再需要extern,并且没有它就可以很好地编译。

从 14.3.2.1 开始,标准声明:

类型、非模板模板参数的模板参数应为以下参数之一:

  • 具有外部链接的对象或函数的地址,包括 函数模板和函数模板 ID,但不包括非静态 类成员,表示为 & id-expression,其中 & 是可选的,如果 名称是指函数或数组,或者如果相应的 模板参数是一个参考;

来自 https://stackoverflow.com/a/643927/451600 by mweerden

extern 关键字表示它将具有外部链接,换句话说,当编译翻译单元时,符号将被导出。因为你的类型是 const,所以默认情况下它具有内部链接(好像它已被声明为 static (。模板不能依赖于仅具有内部链接的类型。

我很想知道原因,但它似乎已经消失在时间的沙子里:为什么 C++03 要求模板参数具有外部链接?

extern 关键字指示变量是在另一个编译单元(源文件(中定义的。

因此,在您的情况下,baz应该在不同的源文件中定义,而 extern 是一种说法,这是一个变量,不是在这个源文件中定义的,而是在不同的源文件中定义的,你会在编译过程中找到它。

extern关键字的意思是"不定义即可声明"。换句话说,它是一种显式声明变量或强制声明而不定义的方法。