提问人:Mati 提问时间:8/15/2023 最后编辑:Jan SchultkeMati 更新时间:8/15/2023 访问量:73
为什么 C++ 变量模板不会引发多个定义错误?[复制]
Why C++ variable template does not raise multiple definitions error? [duplicate]
问:
似乎我缺乏一些关于模板如何工作的基本知识。考虑一个由一个公共头文件组成的程序,该文件引入了一个作为包装器的变量模板和两个包含该头文件的源。std::array
header.h
#ifndef HEADER_H
#define HEADER_H
#include <array>
template <typename T, auto N> std::array<T, N> arr;
void printArr();
#endif
来源1.cpp
#include <iostream>
#include "header.h"
void printArr()
{
std::cout << &arr<int, 5> << std::endl;
}
来源2.cpp
#include <iostream>
#include "header.h"
int main() {
std::cout << &arr<int, 5> << std::endl;
printArr();
return 0;
}
该程序生成以下打印件:
0x565146e1c160
0x565146e1c160
两个打印都生成相同的内存地址,因此正在操作相同的实例。 我的问题是为什么链接器在链接时不会由于多个定义而引发错误?这是因为变量模板只是一个模板,并且模板的各个实例被标记为弱实例,从而生成一个唯一的对象吗?
答:
2赞
Jan Schultke
8/15/2023
#1
对于函数和变量,以及函数模板和变量模板,统一定义规则是放宽的:inline
对于在多个翻译单元中具有定义的任何可定义项目,
D
- if 是非内联非模板化函数或变量,或者
D
- 如果不同翻译单元中的定义不满足以下要求,
程序格式不正确;[...]
简而言之,这些限制意味着可以在多个翻译单元中定义,因为它是一个可变模板。但是,它必须在每个 TU 中以完全相同的方式定义。arr
// source1.cpp
template <typename T, auto N>
std::array<T, N> arr;
// source2.cpp
template <typename T, auto N>
std::array<T, N> arr; // OK
// source3.cpp
template <typename T, auto>
std::array<T, 10> arr; // ill-formed, no diagnostic required
这不会产生链接器错误的原因是发出的符号(例如 它的名字被破坏了)很弱。与变量类似,链接器在假设所有定义都相同的情况下,从 N 个可用定义中选择一个。如果你遵循 [basic.def.odr] 中的规则,那么这个假设是公平的。arr<int, 5>
inline
另见
- 在标头中声明的变量模板是否违反 ODR?(这里的答案解释了历史上C++标准中的措辞)
评论