以下是否真的违反了ODR?

时间:2015-07-27 01:00:22

标签: c++ static inline language-lawyer one-definition-rule

来自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 ++标准的最新工作草案的引用来指定它吗?

1 个答案:

答案 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_constructmagic_number具有内部链接,因此在多个翻译单元中定义内联函数make_magic时,名称piecewise_constructmagic_number指的是不同的实体 - TU 1&#39; make_magic将引用TU 1&{39} piecewise_constructmagic_number,而TU 2&#39; s make_magic将引用TU 2&#39; piecewise_constructmagic_number。由于有问题的tuple的构造函数通过引用获取参数,因此不执行左值到右值的转换,对象使用了odr,并且第二个子弹中的异常不适用,并且您有ODR违规。

(顺便说一下,std::tuple没有piecewise_construct构造函数,并且无论如何这样的构造函数可能会将元组作为参数而不是普通的int,但是#39;与纸张试图制作的点正交。)