将结构传递给具有外部常量模板.外置是干什么用的
Passing a struct to a template with extern const. What is the extern for?
我在问自己为什么以下代码有效以及说明符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
关键字的意思是"不定义即可声明"。换句话说,它是一种显式声明变量或强制声明而不定义的方法。
- #定义c-预处理器常量..我做错了什么
- 用C++中的一个变量定义一个常量
- 什么时候在C++中返回常量引用是个好主意
- 代理对象的常量正确性
- 我想将一个对T类型的非常量左值引用绑定到一个T类型的临时值
- 通过多个头文件使用常量变量
- 在cuda线程之间共享大量常量数据
- 不能在初始值设定项列表中将非常量表达式从类型 'int' 缩小到'unsigned long long'
- 有没有什么方法可以使用一个函数中定义的常量变量,也可以由c++中同一程序中的其他函数使用
- 是默认情况下分配给char数组常量的值
- 私有类型的静态常量成员
- 类似枚举的计算常量
- 递归模板化函数不能分配给具有常量限定类型"const tt &"的变量"state"
- 为什么我可以通过引用修改常量返回
- 如何创建长度由常量参数指定的数组
- 当一个值是非常量但用常量表达式初始化时使用constexpr
- 返回常量对象引用 (getter) 和仅返回字符串有什么区别?
- 隐式常量/非常量运算符布尔
- 非常量变量只读位置的赋值
- 将结构传递给具有外部常量模板.外置是干什么用的