如果声明了对类型的转换操作符和对类型的引用,为什么直接列表初始化会导致类型引用转换的歧义? [英] Why does direct list initialization causes ambiguity for type reference cast if cast operators to the type and reference to the type are declared?
问题描述
在此答案的背景下提出了这个问题.
The question rose in context of this answer.
考虑一个例子:
struct foo {
int value;
operator int&(){ return value; }
operator int(){ return value; }
};
int main () {
int &a(foo{}); // #1
//int &b{foo{}}; // #2 -- ambiguity
int &c = foo{}; // #3
//int &d = {foo{}}; // #4-- ambiguity
int &d { a }; // #5
int &e = { a }; // #6
(void)a;
(void)c;
(void)d;
(void)e;
}
我不明白为什么#2和#4会引起歧义,而#1和#3不会.所以问题是-如果声明了对类型的转换操作符和对类型的引用,为什么直接列表初始化会导致隐式转换对引用的含糊不清?
I don't understand why does #2 and #4 cause ambiguity while #1 and #3 does not. So the question is - why does direct list initialization causes ambiguity for implicit cast to reference if cast operators to the type and reference to the type are declared?
推荐答案
列表初始化用于初始化引用时,将采用列出的值并将其转换为prvalue(aka:临时),该值将用于直接初始化引用.
List initialization, when used to initialize a reference, will take the listed values and convert them into a prvalue (aka: a temporary), which will be used to direct initialize the reference.
因此,int &b{foo{}}
在功能上等同于int &b(int(foo{}))
.这是模棱两可的;它可以通过operator int
或operator int&
生成int
.
So int &b{foo{}}
is functionally equivalent to int &b(int(foo{}))
. Which is ambiguous; it could generate that int
via operator int
or operator int&
.
但是,即使它不是模棱两可的,您仍然会获得对prvalue的非常量左值引用.这是非法的.因此,这段代码永远不会生效.
But even if it wasn't ambiguous, you would still be getting a non-const lvalue reference to a prvalue. Which is illegal. So this code was never going to work.
括号初始列表(大括号)可初始化对象,而不是对象的引用.如果您已经有一个对象并希望获得对该对象的引用,请不要使用braced-init-lists.
Braced-init-lists (curly braces) initialize objects, not references to objects. If you already have an object and want to get a reference to it, don't use braced-init-lists.
但是在这种情况下,为什么编译器会接受#5?
But in this case why does compiler accept #5?
因为列表初始化是一系列具有优先级的规则.优先顺序比我上面指出的优先级高的规则是包含单个值的braced-init-list的情况,后者的类型与正在初始化的类型相同. #5和6恰好适合该条例草案,因为d
,e
和a
都是int&
.
Because list initialization is a series of rules with priority. A rule that has a higher priority than the one I pointed out above is the case of a braced-init-list which contains a single value, who's type is identical to the type of what is being initialized. #5 and 6 just so happen to fit that bill, since d
, e
, and a
are all int&
s.
但是,如果您只是听从我的建议,而在不尝试创建对象时不使用括号初始化列表,那么您就不必担心这种极端情况.
But if you just take my advice and not use braced-init-lists when you're not trying to create an object, you won't have to worry about corner-cases like that.
这篇关于如果声明了对类型的转换操作符和对类型的引用,为什么直接列表初始化会导致类型引用转换的歧义?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!