转发初始化列表表达式
Forwarding initializer list expressions
初始化列表表达式对于初始化C++容器来说真的很方便:
std::vector<int>({1, 2, 3})
...但似乎用大括号括起来的初始化列表表达式,如 {1,2,3}
将 仅 绑定到采用 std::initializer_list<int>
的函数- 它 没有 似乎绑定到 通用(转发)引用 :
template <class T>
void foo(T&& v)
{
std::vector<int>(std::forward<T>(v));
}
int main()
{
foo({1, 2, 3})
}
这输出:
test2.cpp:11:6: note: template<class U> void foo(U&&)
test2.cpp:11:6: note: template argument deduction/substitution failed:
test2.cpp:33:13: note: couldn't deduce template parameter ‘U’
(这是 GCC 4.7.2 的结果。)
不幸的是,这意味着我们无法转发初始化列表表达式。既然这样做会很方便,我想问一下为什么这不起作用?为什么大括号括起来的初始化列表表达式不能绑定到转发引用?或者这是允许的,也许我的编译器太旧了?
不是不能绑定到你函数的参数上;只是编译器无法检测到模板的类型。这编译:
#include <vector>
template <class T>
void foo(T&& v)
{
std::vector<int>(std::forward<T>(v));
}
int main()
{
foo(std::initializer_list<int>{1, 2, 3});
}
在这种情况下无法推导出初始化列表。 [temp.deduct.call]:
中的标准实际上明确涵盖了这一点
Template argument deduction is done by comparing each function template parameter type (call it P
) with
the type of the corresponding argument of the call (call it A
) as described below. If P
is a dependent type,
[...]. Otherwise, an initializer list argument causes the parameter to be considered a non-deduced
context (14.8.2.5). [ Example:
template<class T> void f(std::initializer_list<T>);
f({1,2,3}); // T deduced to int
f({1,"asdf"}); // error: T deduced to both int and const char*
template<class T> void g(T);
g({1,2,3}); // error: no argument deduced for T
此处 g
的示例正是您的情况 - T
不是依赖类型,因此这被认为是非推导上下文。编译器拒绝你的代码是正确的。
初始化列表表达式对于初始化C++容器来说真的很方便:
std::vector<int>({1, 2, 3})
...但似乎用大括号括起来的初始化列表表达式,如 {1,2,3}
将 仅 绑定到采用 std::initializer_list<int>
的函数- 它 没有 似乎绑定到 通用(转发)引用 :
template <class T>
void foo(T&& v)
{
std::vector<int>(std::forward<T>(v));
}
int main()
{
foo({1, 2, 3})
}
这输出:
test2.cpp:11:6: note: template<class U> void foo(U&&)
test2.cpp:11:6: note: template argument deduction/substitution failed:
test2.cpp:33:13: note: couldn't deduce template parameter ‘U’
(这是 GCC 4.7.2 的结果。)
不幸的是,这意味着我们无法转发初始化列表表达式。既然这样做会很方便,我想问一下为什么这不起作用?为什么大括号括起来的初始化列表表达式不能绑定到转发引用?或者这是允许的,也许我的编译器太旧了?
不是不能绑定到你函数的参数上;只是编译器无法检测到模板的类型。这编译:
#include <vector>
template <class T>
void foo(T&& v)
{
std::vector<int>(std::forward<T>(v));
}
int main()
{
foo(std::initializer_list<int>{1, 2, 3});
}
在这种情况下无法推导出初始化列表。 [temp.deduct.call]:
中的标准实际上明确涵盖了这一点Template argument deduction is done by comparing each function template parameter type (call it
P
) with the type of the corresponding argument of the call (call itA
) as described below. IfP
is a dependent type, [...]. Otherwise, an initializer list argument causes the parameter to be considered a non-deduced context (14.8.2.5). [ Example:template<class T> void f(std::initializer_list<T>); f({1,2,3}); // T deduced to int f({1,"asdf"}); // error: T deduced to both int and const char* template<class T> void g(T); g({1,2,3}); // error: no argument deduced for T
此处 g
的示例正是您的情况 - T
不是依赖类型,因此这被认为是非推导上下文。编译器拒绝你的代码是正确的。