来自here:
struct piecewise_construct_t {}; constexpr piecewise_construct_t piecewise_construct = {}; const int magic_number = 42; inline std::tuple<int> make_magic() { return std::tuple<int>( piecewise_construct, magic_number ); }
此功能违反了ODR([basic.def.odr]§3.2/ 6)两次,因为 构造函数2参数都没有收到左值到左值 转换。因此,他们通过地址传递,但地址 取决于TU因为const(和constexpr)意味着内部 键。
我最初认为确实如此,但问题是magic_number
有内部联系。由于它具有内部联系,它不会基本上将magic_number
视为不同翻译单元中的不同变量,因此不是同一变量的多个定义吗?有人可以通过使用C ++标准的最新工作草案的引用来指定它吗?
答案 0 :(得分:8)
问题在于make_magic
。 [basic.def.odr] / P6:
可以有多个内联函数的定义 外部联系(7.1.2)......在一个程序中提供每个 定义出现在不同的翻译单元中,并提供了 定义满足以下要求。鉴于这样的实体 在多个翻译单元中定义的名为
D
,然后
D
的每个定义应由相同的令牌序列组成;和- 在
D
的每个定义中,根据3.4查找的相应名称,应指代D
定义中定义的实体,或者在重载解析后引用同一实体( 13.3)和 匹配部分模板专业化(14.8.3)后,除外 一个名称可以引用内部或。的非易失性const
对象 如果对象在所有定义中具有相同的文字类型,则不进行链接D
的对象,并使用常量表达式(5.20)初始化对象, 并且对象没有使用odr,并且对象具有相同的值D
的所有定义;和- [...]
由于piecewise_construct
和magic_number
具有内部链接,因此在多个翻译单元中定义内联函数make_magic
时,名称piecewise_construct
和magic_number
指的是不同的实体 - TU 1&#39; make_magic
将引用TU 1&{39} piecewise_construct
和magic_number
,而TU 2&#39; s make_magic
将引用TU 2&#39; piecewise_construct
和magic_number
。由于有问题的tuple
的构造函数通过引用获取参数,因此不执行左值到右值的转换,对象使用了odr,并且第二个子弹中的异常不适用,并且您有ODR违规。
(顺便说一下,std::tuple
没有piecewise_construct
构造函数,并且无论如何这样的构造函数可能会将元组作为参数而不是普通的int
,但是#39;与纸张试图制作的点正交。)