模板参数自动推导

转载自https://www.cnblogs.com/zwvista/p/7748363.html

目录
模板参数自动推导
示例
自定义类模板中的应用
Automatic deduction guides(自动推断向导)

模板参数自动推导

在C++17之前,类模板构造器的模板参数是不能像函数模板的模板参数那样被自动推导的,比如我们无法写

1
std::pair a{1, "a" s}; // C++17

而只能写

1
std::pair< int , string> a{1, "a" s}; // C++14

为了弥补这一缺陷,标准库为我们提供了 std::make_pair 函数,通过函数模板的模板参数自动推导的功能,
免去我们在构造 pair 时写模板参数的麻烦。

1
2
3
4
auto a = std::make_pair(1, "a" s); // C++14
// 相当于
// std::pair<int, string> a = std::make_pair<int, string>(1, string("a"));
// 这里编译器根据 std::make_pair 所带参数的类型,自动推导出了函数模板的参数。

这个解决方案其实并不太理想,这是因为:

  1. 我们需要记住 make_pair, make_tuple 这类用于构造模板类的惯用法。
  2. 有些 make_XXX 函数在功能上并不等价于类模板的构造器,比如 make_shared 等等。

在C++17中,这个问题得到了解决,类模板构造器的模板参数同样能够被自动推导

1
2
3
4
std::pair a{1, "a" s}; // C++17
// 相当于
// std::pair<int, string> a{1, "a"s};
// 和函数模板一样,这里编译器根据 std::pair 构造器所带参数类型,自动推导出了构造器模板的参数。

由此我们不再需要 std::make_pair 之类的辅助函数了。

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <iostream>
#include <vector>
#include <functional>
#include <string>
#include <map>
#include <algorithm>
using namespace std;
 
int main()
{
     vector a = {1, 2, 3};  // C++17
//  vector<int> a = {1, 2, 3};  // C++14
     function f = []( int a){ return a + 1;};  // C++17
//  function<int(int)> f = [](int a){return a + 1;};  // C++14
     tuple t{1, 2,5, "a" s};  // C++17
//  tuple<int, double, string> t{1, 2,5, "a"s};  // C++14
//  auto t = make_tuple(1, 2,5, "a"s);  // C++14
     sort(a.begin(), a.end(), greater{}); // C++17
//  sort(a.begin(), a.end(), greater<>{});  // C++14
//  sort(a.begin(), a.end(), greater<int>{});  // C++11
 
//  map m = {{1, "a"s}, {2, "b"s}}; // {1, "a"s} 这种使用大括号的初始化列表没有类型
                                     // 所以编译器无法自动推导 map 类模板的参数类型
     map m = {pair{1, "a" s}, {2, "b" s}}; // C++17
//  map<int, string> m = {{1, "a"s}, {2, "b"s}}; // C++14
}

自定义类模板中的应用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
template < typename T>
struct Container
{
     Container(T* ptr) {} // 构造器 1
     Container(T& v) {} // 构造器 2
     Container(T const & v) {} // 构造器 3
     template < typename D>
     Container(T* ptr, D& deleter) {} // 构造器 4
};
 
struct Deleter {};
 
int main()
{
     Container c{( int *)0}; // 调用构造器 1
     int x; Container c2{x}; // 调用构造器 2
     Container c3{0}; // 调用构造器 3
     Deleter d;
     Container c4{( int *)0, d}; // 调用构造器 4
//  以上编译器自动推导的结果都是 Container<int>
}

Automatic deduction guides(自动推断向导)

有些情况下,编译器无法对类模板的参数做出自动推导,比如下面这种模板参数类型是个嵌套类型的情况。
此时我们需要添加自动推断向导来帮助编译器来进行自动推导。
自动推断向导形式如下:

类模板名(参数列表) -> 类模板id
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
template < typename T>
struct Traits { using type = T; };
 
template < typename T>
struct Container
{
     // 参数类型是嵌套类型,无法进行自动推导
     Container( typename Traits<T>::type v) {}
};
 
// 自动推断向导
template < typename T>
Container(T) -> Container<T>;
 
int main()
{
     Container c(0); //  编译器自动推导的结果是 Container<int>
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
模板参数推导(template argument deduction)是C++11中引入的一个新特性,它可以自动推导模板参数,避免手动指定模板参数。 在使用模板函数或模板类时,通常需要手动指定模板参数,例如: ``` template<typename T> void foo(T t); int main() { foo<int>(1); // 指定模板参数为int return 0; } ``` 在上面的代码中,我们调用了模板函数`foo`,并手动指定了模板参数为int。这种方式比较繁琐,容易出错。 模板参数推导可以自动推导模板参数,避免手动指定模板参数。例如: ``` template<typename T> void foo(T t); int main() { foo(1); // 自动推导模板参数为int return 0; } ``` 在上面的代码中,我们调用了模板函数`foo`,并没有手动指定模板参数,编译器会自动推导模板参数为int。 模板参数推导可以用于函数模板和类模板的实例化过程中。它可以根据函数参数或对象成员的类型,自动推导模板参数的类型。例如: ``` template<typename T, int N> class Array { public: T data[N]; }; int main() { Array arr{1, 2, 3}; // 自动推导模板参数为int和3 return 0; } ``` 在上面的代码中,我们定义了一个类模板`Array`,它有两个模板参数,一个是类型参数T,一个是整型参数N。在实例化`Array`对象时,我们只传入了一个参数{1, 2, 3},编译器会自动推导模板参数为int和3。 需要注意的是,模板参数推导只能用于函数模板和类模板的实例化过程中,不能用于模板定义中。在模板定义中,必须手动指定模板参数

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值