Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/130.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 初始值设定项列表和模板类型推断_C++_Templates_C++11_Initializer List - Fatal编程技术网

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;
}