代码如下:
struct Foo {
Foo(const char *);
};
Foo::Foo(const char *str = 0)
{
}
VS 2013 和 gcc 4.8.0 accept 这样的代码, 而 clang 3.3 拒绝这样的代码:
错误:在重新声明时添加默认参数使该构造函数成为默认构造函数
从标准(C++03 和 C++11)的角度来看,谁是正确的?
注:
我也喜欢 clang 的选择,但是我要向 gcc 和 Visual Studio 报告 bug, 如果从标准角度来看这不正确,这有助于 说服编译器的开发人员解决这个问题。
海湾合作委员会
我在这里描述了问题:http://gcc.gnu.org/bugzilla/show_bug.cgi?id=58194
但不幸的是,他们暂停了错误修复,直到草案成为标准。 演示
这已在 Clang 邮件列表 上进行了讨论,并已作为 缺陷报告 核心问题 1344 提交。
来自邮件列表讨论:
这个想法是某些特殊成员的存在会影响核心 类类型的属性,例如它是 POD 还是 trivially 可复制。决定这些属性不需要整个程序 知识;对我们来说重要的是能够从 类定义。真正有问题的案例是转向 通过添加默认值将“普通”构造函数转换为复制或移动构造函数 参数,但 IIRC 引入默认构造函数也是 有问题。
解决方法是您应该将默认参数放在初始参数中 构造函数的声明。
第 21 工作组在布卢明顿会议上最后讨论了这一问题。笔记来自 那里:
“共识:按照文章中的建议使其格式不正确。核心 问题 1344。优先级 0,Doug 起草。”
因此,CWG(原则上)同意这应该是格式错误的。
TL;DR 每当缺陷得到修复时,Clang 都是对的(不确定这是否只能在 C++14 上正式发生,或者此类委员会决定是否也可以在 C++11 上追溯完成)
我想说CLANG是对的。标准说(新旧版本标准均为 12.1.5):
类 X 的默认构造函数是类 X 的构造函数,可以在不带参数的情况下调用
将默认值添加到构造函数的唯一参数中肯定可以不带参数地调用它,从而使其成为默认值。另外,8.3.6 说(强调我的):
默认参数表达式应在中指定only 参数声明子句 函数声明 <...>
你有一个声明和一个定义。在声明中没有默认值,而在定义中则有默认值。事实上声明的签名与定义的签名非常相似,但又不一样。我认为严格是一个好主意,所以我认为最好强制声明与定义相同。