以下代码可以正常使用:
#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-qualified)X被认为是构造函数的第一个参数 X [...]只考虑标准转换序列和省略号转换序列
所以在我们的例子中,我们考虑了构造函数的参数(它是{B(), B()}
)。更确切地说,我们将initializer-list作为单个参数传递(我引用的规则中的第二个案例)。现在,我们需要将初始化列表的第一个元素(临时类型为B
)转换为int
,唯一的方法是应用用户定义的转换(B::operator int()
)。但是,正如我在引用 的规则末尾所说的那样,只考虑标准转换序列和省略号转换序列 。由于该代码不起作用,因此应该抛出A(int, int)
不可行或类似的错误。
出了什么问题。可能是个错误吗?
答案 0 :(得分:1)
措辞有缺陷并且用C ++ 14改变了。现在[over.best.ics]/4 reads
但是,如果目标是
- 构造函数的第一个参数或
- [...]
并且构造函数或用户定义的转换函数是候选函数 由
- 13.3.1.3,当参数是类复制初始化的第二步中的临时时,
- 13.3.1.4,13.3.1.5或13.3.1.6(在所有情况下)或
- 13.3.1.7的第二阶段,当初始化列表只有一个元素时,目标是第一个参数 类
X
的构造函数,转换为X
或引用 (可能是cv-qualified)X
,不考虑用户定义的转换序列。 [注意:这些 规则阻止应用多个用户定义的转换 在重载决策期间,从而避免无限递归。 - 结束说明]
B()
到int
的转换不在此范围内 - 粗体短语仅适用于复制初始化期间对临时引用的绑定。
但是,Clang rejects this sample code根据以上内容:
class A;
struct B
{
operator A();
};
struct A
{
A(A const&){}
};
A a{B()};