C++ 初始值设定项列表和模板类型推断
考虑以下功能:C++ 初始值设定项列表和模板类型推断,c++,templates,c++11,initializer-list,C++,Templates,C++11,Initializer List,考虑以下功能: template<typename T> void printme(T&& t) { for (auto i : t) std::cout << i; } 我们甚至可以这样写: const auto il = {'a', 'b', 'c'}; printme(il); 或 printme({'a','b','c'}); 这在§14.8.2.5/5中有专门的说明 一种函数参数,其关联参数为 初始值设定项列表,但参数没有 std
template<typename T>
void printme(T&& t) {
for (auto i : t)
std::cout << i;
}
我们甚至可以这样写:
const auto il = {'a', 'b', 'c'};
printme(il);
或
printme({'a','b','c'});
这在§14.8.2.5/5中有专门的说明
一种函数参数,其关联参数为
初始值设定项列表,但参数没有
std::初始值设定项\u列表
或对可能符合条件的cv的引用
std::初始值设定项\u列表
类型。[示例:
template<class T> void g(T);
g({1,2,3}); // error: no argument deduced for T
模板无效g(T);
g({1,2,3});//错误:没有为T推导参数
-[结束示例]
要使其工作,可以显式指定模板参数类型
printme<std::initializer_list<int>>( {1,2,3,4} );
printme({1,2,3,4});
您的第一行printme({'a','b','c'})
是非法的,因为无法推断模板参数T
。如果显式指定模板参数,它将起作用,例如printme({'a','b','c'})
或printme({'a','b','c'})
您列出的其他参数是合法的,因为参数具有定义良好的类型,因此可以很好地推断模板参数T
使用auto
的代码段也可以工作,因为il
被认为是std::initializer\u list
类型,因此可以推断printme()
的模板参数
这里唯一“有趣”的部分是,
auto
将选择类型std::initializer\u list
,但模板参数不会。这是因为C++11标准的§14.8.2.5/5明确规定,这是模板参数的非推断上下文:
一种函数参数,其关联参数为初始值设定项列表(8.5.4),但该参数没有std::initializer\u列表或对可能cv限定的std::initializer\u列表类型的引用。[示例:
模板无效g(T);
g({1,2,3});//错误:没有为T推导参数
-[结束示例]
但是,对于auto
,§7.1.6.4/6明确支持std::initializer\u list
如果初始值设定项是带括号的初始列表(8.5.4),则带有std::initializer\u list
您还可以重载该函数,以显式接受初始值设定项\u list类型的参数
template<typename T>
void printme(std::initializer_list<T> t) {
for (auto i : t)
std::cout << i;
}
模板
void printme(标准::初始值设定项\u列表t){
用于(自动i:t)
std::cout+1我学到了一些东西。这将std::initialiser\u list
提升到普通库函数之外的东西。只是为了完整性。下面是一个解决问题的方法:我们知道为什么会这样吗?如果我想允许模板函数(可能是基于范围的算法),我觉得很奇怪为了获取初始化器列表参数,我必须为std::initializer_list
@JosephMansfield提供重载。我还没有找到一个明确的答案,但我怀疑这与大括号用于统一初始化有关。调用g({1,2,3})
也可以理解为g(Foo(1,2,3))
其中Foo
是任何构造函数包含三个int的类。@4ZM如果在没有参数的情况下调用,则调用不明确。当然,但这会导致其他版本失败,例如printme(std::vector({'a','b','c'))
。很遗憾,模板专门化在这里不起作用。哦,太好了!谢谢你。我以为我已经尝试过了,但我错了。模板专门化在这里很好。因为函数可以完全以相同的方式实现,所以剩下的就是如何找出如何使其中一个调用另一个…很好。你甚至可以通过为初始值设定项列表实现完美转发来改进该解决方案,如下所示:?
printme<std::initializer_list<int>>( {1,2,3,4} );
template<class T> void g(T);
g({1,2,3}); // error: no argument deduced for T
template<typename T>
void printme(std::initializer_list<T> t) {
for (auto i : t)
std::cout << i;
}