- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
这个问题出现在 this answer 的背景下.
如我所料,这个翻译单元无法编译:
template <int Num> int getNum() { return Num; }
template int getNum<0>();
template int getNum<0>(); // error: duplicate explicit instantiation of 'getNum<0>'
int main() { getNum<0>(); return 0; }
我明白这一点,我曾尝试两次进行相同的显式模板实例化。然而,事实证明,将它分成不同的单元,它编译:
// decl.h
template <int Num> int getNum() { return Num; }
// a.cc
#include <decl.h>
template int getNum<0>();
// b.cc
#include <decl.h>
template int getNum<0>();
int main() { getNum<0>(); return 0; }
没想到会这样。我假设具有相同参数的多个显式模板实例化会破坏 ODR,但情况似乎并非如此。然而,这确实失败了:
// decl.h
template <int Num> int getNum();
// a.cc
#include "decl.h"
template <> int getNum<0>() { return 0; }
// b.cc
#include "decl.h"
template <> int getNum<0>() { return 0; }
int main() { getNum<0>(); return 0; }
用户 Oliv帮助我指向 this relevant paragraph in the standard , 但我对此仍然有些困惑,所以我希望有人能用更简单的术语解释这背后的逻辑(例如,什么应该或不应该被认为会破坏 ODR,以及为什么我的期望是错误的)。
编辑:
作为进一步的例子,这里有一个程序分为两个单元,编译正确但它产生了可以说令人惊讶的结果:
// a.cc
template <int Num> int getNum() { return Num + 1; }
template int getNum<0>();
// b.cc
#include <iostream>
template <int Num> int getNum() { return Num; }
template int getNum<0>();
int main() { std::cout << getNum<0>() << std::endl; return 0; }
输出:
1
在这种情况下,删除显式模板实例会产生 0
。我知道拥有两个具有不同定义的模板不是常见的用例,但我认为 ODR 是为了避免此类问题而严格执行的。
最佳答案
Eureka !我终于落在了相关段落上,[temp.spec]/5
For a given template and a given set of template-arguments,
(5.1) an explicit instantiation definition shall appear at most once in a program,
(5.2) an explicit specialization shall be defined at most once in a program, as specified in [basic.def.odr], and
- (5.3) both an explicit instantiation and a declaration of an explicit specialization shall not appear in a program unless the explicit instantiation follows a declaration of the explicit specialization.
An implementation is not required to diagnose a violation of this rule.
因此显式模板实例化定义(而非隐式实例化)可能导致 ODR 违规,不需要诊断(至少 gcc 和 clang - ld 工具链不产生诊断)
关于c++ - 为什么显式模板实例化不会破坏 ODR?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52664184/
我是一名优秀的程序员,十分优秀!