以下是否真的违反了ODR?

Jus*_*tin 7 c++ static inline one-definition-rule language-lawyer

这里:

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 );
}
Run Code Online (Sandbox Code Playgroud)

此函数违反ODR([basic.def.odr]§3.2/ 6)两次,因为构造函数2参数都没有接收到左值到右值的转换.因此它们通过地址传递,但地址取决于TU,因为const(和constexpr)意味着内部链接.

我最初认为它确实如此,但问题是magic_number内部联系.由于它具有内部联系,它不会基本上将magic_number它们视为不同翻译单元中的不同变量,因此不是同一变量的多个定义吗?有人可以通过使用C++标准的最新工作草案的引用来指定这个吗?

T.C*_*.C. 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-used,对象在所有定义中具有相同的值D; 和
  • [...]

由于piecewise_constructmagic_number具有内部链接,当内联函数make_magic在多个翻译单位,名称被定义piecewise_constructmagic_number指不同的实体- TU 1的make_magic将参考TU 1的piecewise_constructmagic_number,和TU 2的make_magic将参考TU 2的piecewise_constructmagic_number.由于有tuple问题的构造函数通过引用获取参数,因此不执行左值到右值的转换,对象使用了odr,第二个项目符号中的异常不适用,并且您有ODR违例.

(顺便说一下,std::tuple没有piecewise_construct构造函数,并且在任何情况下,这样的构造函数可能会将元组作为参数而不是普通的int,但这与文章试图制作的点是正交的.)