通用引用和std :: initializer_list [英] Universal references and std::initializer_list

查看:169
本文介绍了通用引用和std :: initializer_list的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在他的C ++ and Beyond 2012:Universal References介绍中,Scott反复强调,通用引用处理/绑定所有内容,因此重载了一个已经采用通用引用参数的函数没有意义。
我没有理由怀疑,直到我与 std :: initializer_list 混合。

In his "C++ and Beyond 2012: Universal References" presentation, Scott repeatedly stresses the point, that universal references handle/bind to everything and thus overloading a function that already takes a universal reference parameter does not make sense. I had no reason to doubt that until I mingled them with std::initializer_list.

是一个简短的例子:

#include <iostream>
#include <initializer_list>
using namespace std;

template <typename T>
void foo(T&&) { cout << "universal reference" << endl; }

template <typename T>
void foo(initializer_list<T>) { cout << "initializer list" << endl; }

template <typename T>
void goo(T&&) { cout << "universal reference" << endl; }

template <typename T>
void goo(initializer_list<T> const&) { cout << "initializer list" << endl; }

int main(){
    auto il = {4,5,6};
    foo( {1,2,3} );
    foo( il );
    goo( {1,2,3} );
    goo( il );
    return 0;
}

奇怪的是,VC11 11月2012 CTP抱怨歧义( error C2668:'foo':对重载函数的模糊调用)。更令人惊讶的是,gcc-4.7.2,gcc-4.9.0和clang-3.4同意以下输出:

Oddly enough, VC11 Nov 2012 CTP complains about ambiguity (error C2668: 'foo' : ambiguous call to overloaded function). Yet even more suprising is, that gcc-4.7.2, gcc-4.9.0 and clang-3.4 agree on the following output:

initializer list
initializer list
initializer list
universal reference

所以显然有可能使用 initializer_list s,但是当使用 auto + {expr} = > initializer_list -idiom它是否需要 initializer_list by value或 const&
至少对我来说,行为是完全令人惊讶的。
哪些行为符合标准?

So apparently it is possible (with gcc and clang) to overload functions taking universal references with initializer_lists but when using the auto + { expr } => initializer_list-idiom it does even matter whether one takes the initializer_list by value or by const&. At least to me that behavior was totally surprising. Which behavior conforms to the standard? Does anyone know the logic behind that?

推荐答案

这里是crux:从一个braced-init-列表中减去一个类型c $ c> {expr ...} )不适用于模板参数,只有 auto 。使用模板参数,您会得到一个扣除失败,并且重载被删除考虑。这导致第一个和第三个输出。

Here's the crux: Deducing a type from a braced-init-list ({expr...}) doesn't work for template arguments, only auto. With template arguments, you get a deduction failure, and the overload is removed from consideration. This leads to the first and third output.


无论是否使用 initializer_list 按价值或 const&

foo :对于任何 X ,两个重载 X X& 参数对于左值参数来说是不明确的 - 两者都是同样可行的(对于 X vs X&&&&&&& for rvalues)。

foo: For any X, two overloads taking X and X& parameters are ambiguous for an lvalue argument - both are equally viable (same for X vs X&& for rvalues).

struct X{};
void f(X);
void f(X&);
X x;
f(x); // error: ambiguous overloads

然而,部分排序规则在这里(§14.5.6.2)并且采用通用 std :: initializer_list 的函数比通用类型

However, partial ordering rules step in here (§14.5.6.2), and the function taking a generic std::initializer_list is more specialized than the generic one taking anything.

goo :对于两个重载 X& X const& / code>参数和 X& 参数,第一个是更可行的,因为第二个重载需要 X& X const& (§13.3.3.1.2/ 1表12和§ 13.3.3.2/3第三个子项目符号)。

goo: For two overloads with X& and X const& parameters and a X& argument, the first one is more viable because the second overload requires a Qualification conversion from X& to X const& (§13.3.3.1.2/1 Table 12 and §13.3.3.2/3 third sub-bullet).

这篇关于通用引用和std :: initializer_list的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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