C ++ 17标准引入了“模板推导指南”。我认为它们与在该版本标准中引入的针对构造函数的新模板自变量推论有关,但是我还没有看到关于它们的含义和用途的简单的,常见问题解答风格的解释。
什么是C ++ 17中的模板推导指南?
我们为什么(何时)需要它们?
我该如何申报?
C ++ 17标准引入了“模板推导指南”。我认为它们与在该版本标准中引入的针对构造函数的新模板自变量推论有关,但是我还没有看到关于它们的含义和用途的简单的,常见问题解答风格的解释。
什么是C ++ 17中的模板推导指南?
我们为什么(何时)需要它们?
我该如何申报?
Answers:
模板推导指南是与模板类关联的模式,它们告诉编译器如何将一组构造函数参数(及其类型)转换为该类的模板参数。
最简单的示例是std::vector
带有迭代器对的构造函数及其实例。
template<typename Iterator>
void func(Iterator first, Iterator last)
{
vector v(first, last);
}
编译器需要弄清楚什么vector<T>
的T
类型将是。我们知道答案是什么;T
应该是typename std::iterator_traits<Iterator>::value_type
。但是我们如何告诉编译器而不必键入vector<typename std::iterator_traits<Iterator>::value_type>
?
您使用推论指南:
template<typename Iterator> vector(Iterator b, Iterator e) ->
vector<typename std::iterator_traits<Iterator>::value_type>;
这告诉编译器,当您调用 vector
与该模式匹配构造函数时,它将vector
使用右侧的代码来推导专业化->
。
当从参数中推导类型不基于那些参数之一的类型时,您需要指南。初始化一个vector
从initializer_list
明确使用vector
的T
,所以它并不需要一个向导。
左侧不一定指定实际的构造函数。它的工作方式是,如果对类型使用模板构造函数推导,则它将与针对所有推导指南传递的参数相匹配(主模板的实际构造函数提供隐式指南)。如果存在匹配项,它将使用它来确定要提供给该类型的模板参数。
但是一旦推论完成,一旦编译器找出了该类型的模板参数,就对该类型的对象进行初始化,就好像没有发生任何事情一样。也就是说,所选的推导指南不必与所选的构造函数匹配。
这也意味着您可以将指南与汇总和汇总初始化结合使用:
template<typename T>
struct Thingy
{
T t;
};
Thingy(const char *) -> Thingy<std::string>;
Thingy thing{"A String"}; //thing.t is a `std::string`.
因此,推导仅用于确定正在初始化的类型。一旦确定,初始化的实际过程便会像以前一样工作。
vector v{first, last};
也不会做正确的事:(
std::string{32,'*'}[0] == ' '
(对于ASCII)。但是自C ++ 11起,这一切都是正确的。