以下内容是否确实违反了 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_construct
和magic_number
有内部链接,当内联函数make_magic
定义在多个翻译单元时,名称piecewise_construct
和magic_number
引用不同的实体 - TU 1 的 make_magic
将引用 TU 1 的 piecewise_construct
和 magic_number
,而 TU 2 的 make_magic
将引用 TU 2 的 piecewise_construct
和 magic_number
。由于 tuple
的构造函数通过引用获取参数,因此不执行左值到右值的转换,对象是 odr-used,第二个项目符号中的异常不适用,你有一个ODR 违规。
(顺便说一下,std::tuple
没有 piecewise_construct
构造函数,并且在任何情况下,这样的构造函数可能会采用元组作为参数而不是普通的 int
,但这是正交于论文试图表达的观点。)
来自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 ofD
, 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-volatileconst
object with internal or no linkage if the object has the same literal type in all definitions ofD
, 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 ofD
; and- [...]
因为piecewise_construct
和magic_number
有内部链接,当内联函数make_magic
定义在多个翻译单元时,名称piecewise_construct
和magic_number
引用不同的实体 - TU 1 的 make_magic
将引用 TU 1 的 piecewise_construct
和 magic_number
,而 TU 2 的 make_magic
将引用 TU 2 的 piecewise_construct
和 magic_number
。由于 tuple
的构造函数通过引用获取参数,因此不执行左值到右值的转换,对象是 odr-used,第二个项目符号中的异常不适用,你有一个ODR 违规。
(顺便说一下,std::tuple
没有 piecewise_construct
构造函数,并且在任何情况下,这样的构造函数可能会采用元组作为参数而不是普通的 int
,但这是正交于论文试图表达的观点。)