C ++国际标准

时间:2017-04-13 13:35:44

标签: c++ one-definition-rule

有人能否提及比2014-11-19的N4296更近期的C ++国际标准的工作草案?

或者有人可以告诉我3.2.6.6条款中给出的例子 (关于odr规则)是否正确?

我引用它:

 // translation unit 1:
    struct X {
    X(int);
    X(int, int);
    };
    X :: X(int = 0)  {  }

    class D : public X {  };
    D d2;    // X(int) called by D()

   // translation unit 2:
   struct X {
    X(int);
    X(int, int);
    };
   X :: X(int = 0, int = 0)  {  }
   class D : public X {  };   // X(int, int) called by D();
                              // D()'s implicit definition
                              // violates the ODR

关于这个例子我有两个问题:

首先:

标准参数不应该在声明中而不是在定义中指定?如果我将此代码提供给clang编译器(添加 它抱怨的是两个翻译单元之一的一个微不足道的main函数 在两个构造函数定义上,如果我把它放在静默编译 声明中的标准参数。

第二

实际上是IT编译:根本没有发出ODR违规信号。因此,我如何修改代码以使违规行为成为证据呢?

1 个答案:

答案 0 :(得分:4)

每个定义都是一个声明。默认参数可以出现在任何声明中。

clang给出的错误一般与ODR或默认参数无关。它仅适用于default,copy和move构造函数中的默认参数。事实上,只需添加默认参数,就可以将非默认构造函数转换为默认的一个事实,这被认为是标准中的缺陷。有关详细信息,请参阅here。因此,该示例不应该有效,但C ++ 11标准无法明确地使其无效; clang解决了这个问题。 N4296包含8.3.6 / 6的校正:

  

除了类模板的成员函数之外,成员函数定义中的默认参数   出现在类定义之外的内容被添加到成员提供的默认参数集中   类定义中的函数声明;如果默认构造函数(12.1),则程序格式不正确,复制   或移动构造函数,或复制或移动赋值运算符(12.8)如此声明。

因此该示例在N4296中已经无效。不确定上面的段落是否是官方C ++ 14标准的一部分(N4296的某些部分不是)。

ODR违规通常不会被诊断出来。避免ODR违规的唯一方法是严格的头文件规则。