默认参数,gcc vs clang
default argument, gcc vs clang
代码看起来像:
struct Foo {
Foo(const char *);
};
Foo::Foo(const char *str = 0)
{
}
VS 2013和gcc 4.8.0接受这样的代码,而clang 3.3拒绝这样的代码:
错误:在重新声明时添加默认参数会使此构造函数成为默认构造函数
从标准(C++03和C++11)的角度来看,谁是对的?
注:
我也喜欢clang的选择,但我会向gcc和visualstudio报告bug,如果从标准的角度来看这是不正确的,这有助于说服编译器的开发人员解决这个问题。
GCC
我在这里描述了这个问题:http://gcc.gnu.org/bugzilla/show_bug.cgi?id=58194
但运气不好,他们暂停了bug修复,直到草案成为标准。
这已经在Clang邮件列表中进行了讨论,并作为缺陷报告核心问题1344提交。
来自邮件列表讨论:
其理念是,某些特殊成员的存在会影响核心类类型的属性,比如它是POD还是平凡的可复制。决定这些属性不需要整个程序知识对我们来说,仅仅从类定义。真正有问题的案例是通过添加默认值将"normal"构造函数转换为复制或移动构造函数参数,但引入默认构造函数的IIRC也是有问题的
解决方法是,您应该将默认参数放在构造函数的声明。
21工作组最后一次讨论这个问题是在布卢明顿会议上。来自的笔记那里:
"共识:按照文章中的建议,把这件事搞砸。核心第1344期。优先级0,Doug起草。"
因此,CWG(原则上)同意这应该是不合理的。
TL;DRClang在修复缺陷时是正确的(不确定这是否只能在C++14中正式发生,或者委员会的决定是否也可以在C++11上追溯)
我认为CLANG是对的。标准规定(12.1.5适用于标准的新旧版本):
类X的默认构造函数是可以在没有参数的情况下调用的类X的构造函数
将默认值添加到构造函数的唯一参数肯定可以在没有参数的情况下调用它,从而使它成为默认值。此外,8.3.6说(强调我的):
默认参数表达式只能在参数声明子句函数声明的<…>
您有一个声明和一个定义。在声明中没有默认值,而在定义中有默认值。事实上,声明的签名与定义的签名非常相似,但并不相同。我认为严格是个好主意,所以我认为最好强制声明与定义相同。
- 数据成员SFINAE的C++17测试:gcc vs clang
- 为什么在Windows上的VS 2019和Clang 9中"size_t"在没有标题的情况下工作
- CRTP 中的复制赋值运算符 - gcc vs clang 和 msvc
- 命名空间范围内的外部 - GCC vs clang vs msvc
- Visual C++: MSVC vs. GCC+CLANG: 处理 lambda 捕获类成员变量,正确的方法是什么?
- 与clang++一起使用的VS代码在构建良好的C++文件中显示错误
- constexpr 函数的常量引用参数:gcc/msvc vs clang/icc
- 使用函数参数作为常量表达式的一部分 - gcc vs clang
- `noexcept`函数中的std :: terminate`调用函数有限-GCC vs clang codegen
- 函数指针的模板参数推导(g++ & ICC vs Clang++ & VC++)
- GCC vs CLANG:除了静态强制转换时在未使用的模板专用化中解析外,否
- GCC vs CLANG:将捕获的参数包扩展两次
- GCC vs Clang 中的堆栈粉碎(可能是由于金丝雀)
- "Nested" 带括号的类模板参数推导:GCC vs. clang
- GCC vs Clang:将功能与-FPIC一起插入
- cppcheck vs clang整洁:显式构造函数initializer_list
- GCC vs. Clang:"invalid use of incomplete type" std::d eclval 和模板专业化
- 默认参数,gcc vs clang
- GCC vs clang -使用' make_overload '可变lambda继承时的模糊重载
- LLVM vs clang on OS X