什么是模板演绎指南,我们应该在什么时候使用它们?

时间:2022-01-19 20:47:41

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标准引入了“模板演绎指南”。我认为它们与本标准版本中引入的构造函数的新模板参数演绎有关,但是我还没有看到一个简单的faqstyle解释它们是什么以及它们的用途。

  • What are template deduction guides in C++17?

    c++ 17中的模板演绎指南是什么?

  • Why (and when) do we need them?

    我们为什么(以及何时)需要它们?

  • How do I declare them?

    如何申报?

2 个解决方案

#1


54  

Template deduction guides are patterns associated with a template class that tell the compiler how to translate a set of parameter (and their types) into template arguments.

模板演绎指南是与模板类相关联的模式,模板类告诉编译器如何将一组参数(及其类型)转换为模板参数。

The simplest example is that of std::vector and its constructor that takes an iterator pair.

最简单的例子是std::vector及其构造函数,它使用迭代器对。

template<typename Iterator>
void func(Iterator first, Iterator last)
{
  vector v(first, last);
}

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>?

编译器需要计算出向量 的T类型是什么。我们知道答案是什么;T应该是typename std::iterator_traits ::value_type。但是我们如何告诉编译器不需要输入向量 : value_type>?

You use a deduction guide:

使用演绎指南:

template<typename Iterator> vector(Iterator b, Iterator e) -> 
    vector<typename std::iterator_traits<Iterator>::value_type>;

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 ->.

这告诉编译器,当您调用匹配该模式的向量构造函数时,它将使用->右边的代码来推断向量专门化。

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.

当从参数中推导出类型时,您需要向导,而不是基于这些参数的类型。从initializer_list中初始化一个向量显式地使用向量的T,所以它不需要向导。

The left side doesn't necessarily specify a 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 provide implicit guides). If there is a match, it uses that to determine which template arguments to provide to the type. But overload resolution to determine which constructor to call happens after that.

左边不一定指定构造函数。它的工作方式是,如果您对一个类型使用模板构造函数演绎,它将匹配您传递给所有演绎指南的参数(实际构造函数提供隐式向导)。如果存在匹配,它将使用该参数来确定向类型提供哪些模板参数。但是,决定调用哪个构造函数的重载解析在此之后发生。

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.

因此,演绎指南只用于计算要初始化的类型。初始化的实际过程与以前一样工作,一旦确定之后。

#2


-2  

Here is a use case of deduction guide I used to simplify proxy object construction in a proxy pattern. Hope it may give you some ideas simplest things we can do proxy pattern using modern c++ The deduction guides I used are :

下面是我用来简化代理模式中的代理对象构造的演绎指南的一个用例。希望它能给你一些最简单的想法,我们可以用现代c++做代理模式,我用的演绎指南是:

ProxyContainer(vector<string>&) -> ProxyContainer<<vector<string>, string>;

ProxyContainer(int*) -> ProxyContainer<<vector<int>, int>;

#1


54  

Template deduction guides are patterns associated with a template class that tell the compiler how to translate a set of parameter (and their types) into template arguments.

模板演绎指南是与模板类相关联的模式,模板类告诉编译器如何将一组参数(及其类型)转换为模板参数。

The simplest example is that of std::vector and its constructor that takes an iterator pair.

最简单的例子是std::vector及其构造函数,它使用迭代器对。

template<typename Iterator>
void func(Iterator first, Iterator last)
{
  vector v(first, last);
}

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>?

编译器需要计算出向量 的T类型是什么。我们知道答案是什么;T应该是typename std::iterator_traits ::value_type。但是我们如何告诉编译器不需要输入向量 : value_type>?

You use a deduction guide:

使用演绎指南:

template<typename Iterator> vector(Iterator b, Iterator e) -> 
    vector<typename std::iterator_traits<Iterator>::value_type>;

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 ->.

这告诉编译器,当您调用匹配该模式的向量构造函数时,它将使用->右边的代码来推断向量专门化。

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.

当从参数中推导出类型时,您需要向导,而不是基于这些参数的类型。从initializer_list中初始化一个向量显式地使用向量的T,所以它不需要向导。

The left side doesn't necessarily specify a 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 provide implicit guides). If there is a match, it uses that to determine which template arguments to provide to the type. But overload resolution to determine which constructor to call happens after that.

左边不一定指定构造函数。它的工作方式是,如果您对一个类型使用模板构造函数演绎,它将匹配您传递给所有演绎指南的参数(实际构造函数提供隐式向导)。如果存在匹配,它将使用该参数来确定向类型提供哪些模板参数。但是,决定调用哪个构造函数的重载解析在此之后发生。

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.

因此,演绎指南只用于计算要初始化的类型。初始化的实际过程与以前一样工作,一旦确定之后。

#2


-2  

Here is a use case of deduction guide I used to simplify proxy object construction in a proxy pattern. Hope it may give you some ideas simplest things we can do proxy pattern using modern c++ The deduction guides I used are :

下面是我用来简化代理模式中的代理对象构造的演绎指南的一个用例。希望它能给你一些最简单的想法,我们可以用现代c++做代理模式,我用的演绎指南是:

ProxyContainer(vector<string>&) -> ProxyContainer<<vector<string>, string>;

ProxyContainer(int*) -> ProxyContainer<<vector<int>, int>;