为什么 C++ 变量模板不会引发多个定义错误?[复制]

Why C++ variable template does not raise multiple definitions error? [duplicate]

提问人:Mati 提问时间:8/15/2023 最后编辑:Jan SchultkeMati 更新时间:8/15/2023 访问量:73

问:

似乎我缺乏一些关于模板如何工作的基本知识。考虑一个由一个公共头文件组成的程序,该文件引入了一个作为包装器的变量模板和两个包含该头文件的源。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

两个打印都生成相同的内存地址,因此正在操作相同的实例。 我的问题是为什么链接器在链接时不会由于多个定义而引发错误?这是因为变量模板只是一个模板,并且模板的各个实例被标记为弱实例,从而生成一个唯一的对象吗?

C++ 模板 language-lawyer

评论


答:

2赞 Jan Schultke 8/15/2023 #1

对于函数和变量,以及函数模板和变量模板,统一定义规则是放宽的:inline

对于在多个翻译单元中具有定义的任何可定义项目,D

  • if 是非内联非模板化函数或变量,或者D
  • 如果不同翻译单元中的定义不满足以下要求,

程序格式不正确;[...]

- [basic.def.odr] 第 14 页

简而言之,这些限制意味着可以在多个翻译单元中定义,因为它是一个可变模板。但是,它必须在每个 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


另见