问题 使用rvalue initializer_list进行类型推断


在以下代码中

#include <initializer_list>
#include <utility>

template<typename T> void f(T&& x) {}
template<typename T> void g(std::initializer_list<T> x) {}

int main()
{
    auto   x = {0}; // OK
    auto&& y = {0}; // OK
    g(x); // OK
    g(std::move(x)); // OK
    g({0}); // OK
    f(x); // OK
    f(std::move(x)); // OK
    f({0}); // failure
    return 0;
}

右值 initializer_list 可以推断出来 auto 但没有 template

为什么C ++会禁止这个?


5040
2017-07-05 20:14


起源

可能是因为 {0} 被视为一种“文字初始化器”,并且直观地说,你不能从文字移动(或者有一个右移参考你可以移动的文字)。 - Mark B
你错过了 #include <utility>, 顺便一提。 - chris
@chris - 你是对的。我会编辑 - a.lasram
为什么委员会会对此产生影响 这个问题。 - xskxzr


答案:


我相信这是由于14.8.2.1/1:

[...]初始化列表参数使参数被视为非推导的上下文(14.8.2.5)。 [例: [...]

template<class T> void g(T);
g({1,2,3});                    // error: no argument deduced for T

- 最后的例子]

现在你可能会想到这一点 auto 只是模板参数推导,但对于支撑列表 auto 在7.1.6.4/6接受特殊待遇:

替换的发生 auto 使用新发明的类型模板参数U或者,如果初始化器是a 支撑-初始化列表 (8.5.4),带 std::initializer_list<U>。 [...] [

auto x1 = { 1, 2 };   // decltype(x1) is std::initializer_list<int>

- 最后的例子]


9
2017-07-05 20:27



必须有一些奇怪的案例,使委员会只对汽车给予特殊待遇 - a.lasram
@ a.lasram:我认为允许它没有坏处 auto x = { 1, 2, 3 };所以你不妨拥有它。另一方面,它 将 可能会伤害允许模板参数推导(我在思考构造函数)。 - Kerrek SB