正在转发初始值设定项列表表达式
Forwarding initializer list expressions
Initializer列表表达式对于初始化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.dexecute.call〕中的标准明确涵盖的:
模板参数推导是通过将每个函数模板参数类型(称为
P
)与调用的相应参数的类型(称之为A
),如下所述。如果CCD_ 5是依赖类型,[…]。否则,初始值设定项列表参数会导致该参数被视为非推导参数上下文(14.8.2.5)。[示例: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
不是依赖类型,所以这被认为是一个非推导上下文。编译器拒绝您的代码是正确的。
相关文章:
- 不能在初始值设定项列表中将非常量表达式从类型 'int' 缩小到'unsigned long long'
- 概念中的cv限定符需要表达式参数列表
- C++模板函数中的初始化 - 新的初始值设定项表达式列表被视为复合表达式
- 使用正则表达式获取大括号块的列表
- C++:带有大括号初始化列表的函数调用表达式 - 标准是否规定在单个元素列表的微不足道的情况下忽略大括号?
- 列表.erase 中的 lambda 表达式
- 为什么初始值设定项列表与表达式列表的结果不同
- 将任何类型的表达式放在 c++ 的初始化列表中在语法上是否正确?
- C++ 包含表达式的初始化列表
- 射击时从列表中删除外星人 - 找出循环;"表达式:无法递增结束列表迭代器"
- 使用 STD 正则表达式标记逗号分隔的列表
- C 套接字误差(新的初始器表达式列表被视为复合表达式)
- 错误:表达式列表在初始化器[-fpermissive] Double Paycalc(p,yir,y)中被视为复合表达式
- 可变模板:表达式列表在函数转换错误中被视为复合表达式
- 为什么 lambda 表达式的捕获列表无法使用结构化绑定分解
- Makefile中扩展正则表达式列表的分隔符
- 表达式列表被视为复合表达式
- boost正则表达式中的命名捕获/组列表
- 正在转发初始值设定项列表表达式
- 编写布尔表达式以判断列表是否在增加