使用 extern const 将结构传递给模板。什么是外部?
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
说明符在此示例中的作用是什么?
extern
关键字表示该变量是在另一个编译单元(源文件)中定义的。
所以在你的情况下,baz
应该 在不同的源文件中定义,extern 是一种表示这是一个未在此源文件中定义的变量的方式, 但在不同的地方,你会在编译时找到它。
关键字extern
表示"declare without defining"。换句话说,它是一种显式声明变量的方法,或者强制声明没有定义。
从 14.3.2.1 开始,标准规定:
A template-argument for a non-type, non-template template-parameter shall be one of:
- the address of an object or function with external linkage, including
function templates and function template-ids but excluding non-static
class members, expressed as & id-expression where the & is optional if
the name refers to a function or array, or if the corresponding
template-parameter is a reference;
来自 作者:mweerden
extern
关键字意味着它会有外部链接,换句话说,编译单元时会导出符号。因为您的类型是 const,所以默认情况下它具有内部链接(就好像它已被声明为 static
)。模板不能依赖于只有内部链接的类型。
我很想知道原因,但它似乎已经消失在时间的流逝中:Why did C++03 require template parameters to have external linkage?。
这是标准中从 C++03 更改为 C++11 的部分之一。
在 C++03 中,[temp.arg.nontype] 表示:
A template-argument for a non-type, non-template template-parameter shall be one of:
- [...]
- [...]
- the address of an object or function with external linkage, including function templates and function template-ids but excluding non-static class members, expressed as & id-expression where the & is optional if the name refers to a function or array, or if the corresponding template-parameter is a reference; or
- [...]
在 C++11 中,issue 1155, though GCC still has a bug 更新了关于此行为的结果:
- a constant expression (5.19) that designates the address of a complete object with static storage duration
and external or internal linkage or a function with external or internal linkage, including function
templates and function template-ids but excluding non-static class members, expressed (ignoring parentheses)
as & id-expression, where the id-expression is the name of an object or function, except that the
& may be omitted if the name refers to a function or array and shall be omitted if the corresponding
template-parameter is a reference; or
在 C++14 中,这得到了进一步简化,甚至没有提到链接。
关于您的具体问题,extern
说明符将外部链接添加到 baz_instance
。没有它,baz_instance
有内部链接。在 C++03 中,您需要外部链接才能拥有引用类型的非类型模板参数。在 C++11 中,你不再需要 - 所以 extern
不再是必需的,没有它它编译得很好。
我在问自己为什么下面的代码有效以及说明符 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
说明符在此示例中的作用是什么?
extern
关键字表示该变量是在另一个编译单元(源文件)中定义的。
所以在你的情况下,baz
应该 在不同的源文件中定义,extern 是一种表示这是一个未在此源文件中定义的变量的方式, 但在不同的地方,你会在编译时找到它。
关键字extern
表示"declare without defining"。换句话说,它是一种显式声明变量的方法,或者强制声明没有定义。
从 14.3.2.1 开始,标准规定:
A template-argument for a non-type, non-template template-parameter shall be one of:
- the address of an object or function with external linkage, including function templates and function template-ids but excluding non-static class members, expressed as & id-expression where the & is optional if the name refers to a function or array, or if the corresponding template-parameter is a reference;
来自 作者:mweerden
extern
关键字意味着它会有外部链接,换句话说,编译单元时会导出符号。因为您的类型是 const,所以默认情况下它具有内部链接(就好像它已被声明为 static
)。模板不能依赖于只有内部链接的类型。
我很想知道原因,但它似乎已经消失在时间的流逝中:Why did C++03 require template parameters to have external linkage?。
这是标准中从 C++03 更改为 C++11 的部分之一。
在 C++03 中,[temp.arg.nontype] 表示:
A template-argument for a non-type, non-template template-parameter shall be one of:
- [...]
- [...]
- the address of an object or function with external linkage, including function templates and function template-ids but excluding non-static class members, expressed as & id-expression where the & is optional if the name refers to a function or array, or if the corresponding template-parameter is a reference; or
- [...]
在 C++11 中,issue 1155, though GCC still has a bug 更新了关于此行为的结果:
- a constant expression (5.19) that designates the address of a complete object with static storage duration and external or internal linkage or a function with external or internal linkage, including function templates and function template-ids but excluding non-static class members, expressed (ignoring parentheses) as & id-expression, where the id-expression is the name of an object or function, except that the & may be omitted if the name refers to a function or array and shall be omitted if the corresponding template-parameter is a reference; or
在 C++14 中,这得到了进一步简化,甚至没有提到链接。
关于您的具体问题,extern
说明符将外部链接添加到 baz_instance
。没有它,baz_instance
有内部链接。在 C++03 中,您需要外部链接才能拥有引用类型的非类型模板参数。在 C++11 中,你不再需要 - 所以 extern
不再是必需的,没有它它编译得很好。