为什么 gcc 和 clang 各自为这个程序产生不同的输出?(转换运算符与构造函数)
Why do gcc and clang each produce different output for this program? (conversion operator vs constructor)
program:
#include <stdio.h>
struct bar_t {
int value;
template<typename T>
bar_t (const T& t) : value { t } {}
// edit: You can uncomment these if your compiler supports
// guaranteed copy elision (c++17). Either way, it
// doesn't affect the output.
// bar_t () = delete;
// bar_t (bar_t&&) = delete;
// bar_t (const bar_t&) = delete;
// bar_t& operator = (bar_t&&) = delete;
// bar_t& operator = (const bar_t&) = delete;
};
struct foo_t {
operator int () const { return 1; }
operator bar_t () const { return 2; }
};
int main ()
{
foo_t foo {};
bar_t a { foo };
bar_t b = static_cast<bar_t>(foo);
printf("%d,%dn", a.value, b.value);
}
GCC 7/8 的输出:
2,2
CLANG 4/5 的输出(也适用于 GCC 6.3(
1,1
创建bar_t
实例时似乎发生了以下情况:
对于 gcc,它calls foo_t::operator bar_t
然后constructs bar_t with T = int
.
对于叮当声,它constructs bar_t with T = foo_t
然后calls foo_t::operator int
哪个编译器在这里是正确的?(或者如果这是某种形式的未定义行为,它们可能是正确的(
我相信clang的结果是正确的。
在直接列表初始化bar_t a { foo }
和用户定义类型之间的static_cast中,目标类型的构造函数先于源类型的用户定义转换运算符(C++14 [dcl.init.list]/3 [expr.static.cast]/4(。如果重载解析找到合适的构造函数,则使用它。
当执行重载解析时,bar_t::bar_t<foo_t>(const foo_t&)
是可行的,并且比与此模板的任何实例化更匹配,从而导致在 foo 上使用强制转换运算符。它也比任何默认声明的构造函数更好,因为它们接受 foo_t
以外的其他东西,因此使用了 bar_t::bar_t<foo_t>
。
当前编写的代码取决于 C++17 保证复制 elision;如果您在没有 C++17 保证复制省略的情况下进行编译(例如 -std=c++14
(则 clang 由于 bar_t b = static_cast<bar_t>(foo);
中的复制初始化而拒绝此代码。
相关文章:
- 通过构造函数方法输出的类到类类型转换是 5500 为什么不是 5555
- 在插入容器之前转换输出迭代器
- 字符数组到十六进制字符串的转换 - 意外输出
- 将ctypes c_void_p强制转换为c输出参数
- 使用递归函数 (c++) 将长字符串转换为整数时输出错误
- 输出使用 cout 转换为 ASCII 的文本时输出格式不正确,C++
- 输入 1024 后十进制到二进制转换的输出错误?
- 为什么 gcc 和 clang 各自为这个程序产生不同的输出?(转换运算符与构造函数)
- 有没有一种简单的方法可以将系统命令的输出转换为字符串
- 将Botan SHA256输出转换为base64,以匹配.NET SHA256 MALAGENG().computeHa
- 将ls输出转换为整数
- 将 LibSVM 输出转换为浮点数向量
- 使用x264将OpenGL输出转换为H264
- 如何将发送到stdout的输出转换为字符串
- 如何将Arduino的串行输出转换为插座输出(局域网)
- 将一个C程序的输出转换到另一个C程序的变量中
- c++输出转换错误
- 如何将 warn() 的输出转换为字符串?
- 如何将OpenCV的MatExpr的C包装器的指针输出转换回MatExpr。
- 在c++中将十六进制输出转换为十进制