Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 将结构传递给具有extern const的模板。外景是干什么的?_C++_Templates_Struct_Constants_Extern - Fatal编程技术网

C++ 将结构传递给具有extern const的模板。外景是干什么的?

C++ 将结构传递给具有extern const的模板。外景是干什么的?,c++,templates,struct,constants,extern,C++,Templates,Struct,Constants,Extern,我在问自己为什么下面的代码会工作,以及在实例化baz_实例时,说明符extern做了什么: 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; } structb

我在问自己为什么下面的代码会工作,以及在实例化
baz_实例时,说明符
extern
做了什么:

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;
}
structbaz{
int值;
};
extern const baz baz_实例={3};
模板
int foo(){
返回b.value;
}
int main(){
foo();
返回1;
}

为什么上面的代码首先要编译,如果省略了
extern
说明符,为什么不再编译?
extern
说明符在本例中做什么?

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

因此,在您的情况下,
baz
应该在不同的源文件中定义,extern是一种表示这是一个未在此源文件中定义的变量,但在不同的源文件中定义,您将在编译过程中找到它


extern
关键字表示“声明而不定义”。换句话说,它是一种显式声明变量的方法,或在没有定义的情况下强制声明的方法。

来自14.3.2.1的标准规定:

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

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

从mweerden开始,
extern
关键字意味着它将具有外部链接,换句话说,在编译翻译单元时将导出符号。因为您的类型是const,所以默认情况下它具有内部链接(就好像它已被声明为
static
)。模板不能依赖于仅具有内部链接的类型


我很想知道原因,但它似乎已经消失在时间的沙子里了:。

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

在C++03中,[temp.arg.nontype]读取:

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

  • [……]
  • [……]
  • 具有外部链接的对象或函数的地址,包括函数模板和函数模板id,但不包括非静态类成员,表示为&id表达式,如果名称引用函数或数组,或者如果相应的模板参数是引用,则&id是可选的;或
  • [……]
在C++11中,由于以下原因进行了更新,尽管GCC对此行为仍有以下方面:

  • 一种常量表达式(5.19),用于指定具有静态存储持续时间的完整对象的地址 以及外部或内部链接或具有外部或内部链接的功能,包括 模板和函数模板ID,但不包括非静态类成员,表示(忽略括号) as&id表达式,其中id表达式是对象或函数的名称,但 &如果名称引用函数或数组,则可以省略,如果相应的 模板参数是一个参考;或
在C++14中,这变得更加简化,甚至没有提到链接


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

从源代码中可以看到,baz没有在另一个源文件中定义。此外,它不会解释为什么结构实例可以通过外部传递给模板,但如果没有外部传递则不能。