什么是模板推导指南,我们应该在什么时候使用它们?
C++17 标准引入了模板推导指南".我认为它们与此版本标准中引入的构造函数的新模板参数推导有关,但我还没有看到关于它们是什么以及它们的用途的简单的、常见问题解答式的解释.
The C++17 standard introduces "template deduction guides". I gather they're something to do with the new template argument deduction for constructors introduced in this version of the standard, but I haven't yet seen a simple, FAQ-style explanation of what they are and what they're for.
什么是 C++17 中的模板推导指南?
What are template deduction guides in C++17?
我们为什么(以及何时)需要它们?
Why (and when) do we need them?
我如何声明它们?
推荐答案
模板推导指南是与模板类相关联的模式,它告诉编译器如何将一组构造函数参数(及其类型)转换为类的模板参数.
Template deduction guides are patterns associated with a template class that tell the compiler how to translate a set of constructor arguments (and their types) into template parameters for the class.
最简单的例子是 std::vector
及其采用迭代器对的构造函数.
The simplest example is that of std::vector
and its constructor that takes an iterator pair.
template<typename Iterator>
void func(Iterator first, Iterator last)
{
vector v(first, last);
}
编译器需要弄清楚 vector
的 T
类型是什么.我们知道答案是什么;T
应该是 typename std::iterator_traits
.但是我们如何告诉编译器而不必输入vector
?
The compiler needs to figure out what vector<T>
's T
type will be. We know what the answer is; T
should be typename std::iterator_traits<Iterator>::value_type
. But how do we tell the compiler without having to 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
特化 ->
This tells the compiler that, when you call a vector
constructor matching that pattern, it will deduce the vector
specialization using the code on the right of ->
.
当从参数中推导出类型不是基于这些参数之一的类型时,您需要指南.从 initializer_list
初始化一个 vector
显式使用 vector
的 T
,所以它不需要指南.
You need guides when the deduction of the type from the arguments is not based on the type of one of those arguments. Initializing a vector
from an initializer_list
explicitly uses the vector
's T
, so it doesn't need a guide.
左侧不一定指定实际的构造函数.它的工作方式是,如果您在类型上使用模板构造函数推导,它会匹配您针对所有推导指南传递的参数(主模板的实际构造函数提供隐式指南).如果匹配,它会使用它来确定提供给类型的模板参数.
The left side doesn't necessarily specify an actual constructor. The way it works is that, if you use template constructor deduction on a type, it matches the arguments you pass against all deduction guides (actual constructors of the primary template provide implicit guides). If there is a match, it uses that to determine which template arguments to provide to the type.
但是一旦推导完成,一旦编译器计算出该类型的模板参数,该类型的对象的初始化就会继续进行,就好像这些都没有发生一样.也就是说,选择的推导指南不必与选择的构造函数相匹配.
But once that deduction is done, once the compiler figures out the template parameters for the type, initialization for the object of that type proceeds as if none of that happened. That is, the deduction guide selected does not have to match the constructor selected.
这也意味着您可以使用带有聚合和聚合初始化的指南:
This also means that you can use guides with aggregates and aggregate initialization:
template<typename T>
struct Thingy
{
T t;
};
Thingy(const char *) -> Thingy<std::string>;
Thingy thing{"A String"}; //thing.t is a `std::string`.
所以推导指南仅用于找出被初始化的类型.一旦做出决定,初始化的实际过程与之前完全一样.
So deduction guides are only used to figure out the type being initialized. The actual process of initialization works exactly as it did before, once that determination has been made.
相关文章