如果声明了对类型的转换操作符和对类型的引用,为什么直接列表初始化会导致类型引用转换的歧义? [英] Why does direct list initialization causes ambiguity for type reference cast if cast operators to the type and reference to the type are declared?

查看:94
本文介绍了如果声明了对类型的转换操作符和对类型的引用,为什么直接列表初始化会导致类型引用转换的歧义?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

此答案的背景下提出了这个问题.

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 intoperator 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恰好适合该条例草案,因为dea都是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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆