有人能否提及比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违规信号。因此,我如何修改代码以使违规行为成为证据呢?
答案 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违规的唯一方法是严格的头文件规则。