以下内容是否确实违反了 ODR?

Does the following actually violate the ODR?

来自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 );
}

This function violates the ODR ([basic.def.odr] §3.2/6 ) twice because neither of the constructor 2 arguments receives an lvalue-to-rvalue conversion. They are therefore passed by address, but the address depends on the TU because const (and constexpr) implies internal linkage.

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

问题出在 make_magic。 [basic.def.odr]/p6:

There can be more than one definition of ... inline function with external linkage (7.1.2) ... in a program provided that each definition appears in a different translation unit, and provided the definitions satisfy the following requirements. Given such an entity named D defined in more than one translation unit, then

  • each definition of D shall consist of the same sequence of tokens; and
  • in each definition of D, corresponding names, looked up according to 3.4, shall refer to an entity defined within the definition of D, or shall refer to the same entity, after overload resolution (13.3) and after matching of partial template specialization (14.8.3), except that a name can refer to a non-volatile const object with internal or no linkage if the object has the same literal type in all definitions of D, and the object is initialized with a constant expression (5.20), and the object is not odr-used, and the object has the same value in all definitions of D; and
  • [...]

因为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-used,第二个项目符号中的异常不适用,你有一个ODR 违规。

(顺便说一下,std::tuple 没有 piecewise_construct 构造函数,并且在任何情况下,这样的构造函数可能会采用元组作为参数而不是普通的 int,但这是正交于论文试图表达的观点。)