【发布时间】:2012-10-01 16:59:36
【问题描述】:
这个程序合法吗?
struct X { X(const X &); };
struct Y { operator X() const; };
int main() {
X{Y{}}; // ?? error
}
在n2672 之后,经defect 978 修改,13.3.3.1 [over.best.ics] 具有:
4 - 但是,当考虑构造函数或用户定义的转换函数的参数时,它是 13.3.1.7 [...] 的候选 [...] 当初始化器列表只有一个元素并且转换为某些类 X 或对(可能是 cv 限定的)X 的引用被认为是 X [...] 的构造函数的第一个参数,仅考虑标准转换序列和省略号转换序列。
这似乎有点不合常理;结果是使用列表初始化强制转换指定转换是非法的:
void f(X);
f(Y{}); // OK
f(X{Y{}}); // ?? error
据我了解n2640,列表初始化应该能够替换直接初始化和复制初始化的所有用途,但似乎没有办法从类型对象构造X 类型的对象Y 仅使用列表初始化:
X x1(Y{}); // OK
X x2 = Y{}; // OK
X x3{Y{}}; // ?? error
这是标准的实际意图吗?如果不是,应该如何阅读或阅读?
【问题讨论】:
-
列表初始化不应该能够取代直接初始化和复制初始化的所有用途。我们需要找到传播这种错误信息的人。 ://
-
更令人困惑的是,在同一段落中,
X x2 = Y{};也应该是非法的,因为它属于 13.3.1.3 部分(“当调用用于复制/移动临时类复制初始化的第二步”)。这里可能还有更多事情要做。 -
@NicolBolas 我认为类复制初始化的第一步是使用转换运算符获取(临时)X,第二步从该 X 复制。或者至少这就是我的阅读方式...
-
@MooingDuck 不过,这两种初始化方法之间的特殊差异似乎很奇怪。特别是因为如果您传递 second
Y(当然并相应地修改构造函数),它会起作用。我在下面的回答包含更多细节。 -
@MooingDuck Stroustrup 的 uniform initializer ideal 是(或曾经是)“一种可以在任何地方和任何地方使用的单一语法,相同的初始化值会产生相同的初始化值 " - 这不是主张替换其他初始化语法吗?
标签: c++ c++11 implicit-conversion list-initialization