为什么在初始化期间应用用户定义的转换
Why does user-defined conversion applied during the initialization?
以下代码工作正常:
#include <iostream>
struct B
{
operator int()
{
return int();
}
};
struct A
{
A(int, int){ std::cout << "A(int, int)" << std::endl; }
};
A a({B(), B()});
int main()
{
}
并产生输出:
A(int, int)
演示
但我不明白为什么?标准说的是:
但是,当考虑构造函数或 用户定义的转换函数,在 13.3.1.3 中是候选函数,当 在第二步中为复制/移动临时而调用 类复制初始化,传递初始值设定项时由 13.3.1.7 列表作为单个参数或当初始值设定项列表只有一个参数时 元素并转换为某个类 X 或引用(可能 符合 cv 标准(X 被视为构造函数的第一个参数 的 X [...] 仅考虑标准转换序列和省略号转换序列
所以在我们的例子中,我们考虑了构造函数的参数(它是{B(), B()}
(。更准确地说,我们将初始值设定项列表作为单个参数传递(我引用的规则中的第二种情况(。现在,我们需要将初始值设定项列表的第一个元素(临时类型为 B
(转换为 int
,唯一的方法是应用用户定义的转换 ( B::operator int()
(。但是,正如规则末尾所说,我只引用了标准转换序列,并且考虑了省略号转换序列。由于该代码不应该工作,因此它应该抛出错误,例如A(int, int)
不可行或某种错误。
怎么了。可能是错误?
措辞有缺陷,并随着 C++14 而更改。现在 [over.best.ics]/4 读取
但是,如果目标是
- 构造函数的第一个参数或
- [...]
并且构造函数或用户定义的转换函数是候选函数 由
- 13.3.1.3,当参数是类复制初始化第二步中的临时参数时,
13.3.1.4、13.3.1.5或- 13.3.1.6(在所有情况下(,或
- 13.3.1.7 的第二阶段,当初始值设定项列表只有一个元素时,目标是 类
X
的构造函数,并且转换是X
或引用 (可能符合简历标准(X
,不考虑用户定义的转换序列。[ 注:这些 规则阻止应用多个用户定义的转化 在重载解析期间,从而避免无限递归。— 尾注 ]
这不包括将B()
转换为int
- 粗体短语仅适用于在复制初始化期间绑定对临时引用的引用。
但是,Clang 根据上述内容拒绝了此示例代码:
class A;
struct B
{
operator A();
};
struct A
{
A(A const&){}
};
A a{B()};
相关文章:
- 创建一个函数以在输入为负数或零时输出字符串.第一次执行用户定义的函数
- 使用用户定义函数的字符串反转
- 用户定义函数中的指针和输入
- Visual C++(VS2017)中用户定义的转换不明确
- 使用用户定义的参数调用future/async并调用类方法
- 带有用户定义类的c++折叠表达式
- g++用户定义的动态链接库上的全局new和delete运算符
- 直接在 unordered_map 的方法中使用哈希,而不是生成哈希的用户定义对象
- 修改"std::set"中用户定义类型的值
- 参数包构造函数在类模板中隐藏用户定义的转换
- MAKE:找不到包含的用户定义的头文件?
- C++:用户定义的显式类型转换函数错误
- 从用户定义的类生成格式字符串?
- 为用户定义的类正确调用复制构造函数/赋值运算符
- C++ 向量与用户定义的类比较?(==, <, >)
- STL 用户定义的二进制操作
- 将用户定义的类型与 std::vector 和 std::sort 一起使用
- 为什么用户定义的函数不按照给定的顺序对相同长度的元素进行排序?
- 使用宏编译时使用用户定义的数学函数,或者仅使用 c++ 中标准数学库中的函数
- C++:用户定义的类,以成员字段作为地址