有人可以给我参考比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
功能)它抱怨 在两个构造函数定义上,而如果我把 声明中的标准参数。
第二:
事实上,它编译:根本没有发出违反 ODR 的信号。因此,我如何修改代码以使违规行为成为证据?
每个定义都是一个声明。默认参数可以存在于任何声明中。
clang 给出的错误与 ODR 或一般的默认参数无关。它专门涉及默认、复制和移动构造函数中的默认参数。只需添加默认参数即可将非默认构造函数转换为默认的 one 事后构造函数,这一事实被认为是标准中的缺陷。有关更多信息,请参阅此处。因此,该示例不应有效,但 C++11 标准未能明确使其无效;叮当解决了这个问题。N4296 包含 8.3.6/6 中的更正:
除类模板的成员函数外,成员函数定义中的默认参数 出现在类定义之外 被添加到成员提供的默认参数集中 类定义中的函数声明;如果默认构造函数 (12.1),则程序格式不正确,复制 或移动构造函数,或复制或移动赋值运算符 (12.8) 如此声明。
因此,该示例在 N4296 中已经无效。不确定上面的段落是否是官方 C++14 标准的一部分(N4296 的某些部分不是)。
ODR违规行为通常不会被诊断。避免 ODR 冲突的唯一方法是严格的头文件规则。