C++17尝鲜:类模板中的模板参数自动推导
模板参数自动推导
在C++17之前,类模板构造器的模板参数是不能像函数模板的模板参数那样被自动推导的,比如我们无法写
std::pair a{1, "a"s}; // C++17
而只能写
std::pair<int, string> a{1, "a"s}; // C++14
为了弥补这一缺陷,标准库为我们提供了 std::make_pair 函数,通过函数模板的模板参数自动推导的功能,
免去我们在构造 pair 时写模板参数的麻烦。
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 所带参数的类型,自动推导出了函数模板的参数。
这个解决方案其实并不太理想,这是因为:
- 我们需要记住 make_pair, make_tuple 这类用于构造模板类的惯用法。
- 有些 make_XXX 函数在功能上并不等价于类模板的构造器,比如 make_shared 等等。
在C++17中,这个问题得到了解决,类模板构造器的模板参数同样能够被自动推导
std::pair a{1, "a"s}; // C++17
// 相当于
// std::pair<int, string> a{1, "a"s};
// 和函数模板一样,这里编译器根据 std::pair 构造器所带参数类型,自动推导出了构造器模板的参数。
由此我们不再需要 std::make_pair 之类的辅助函数了。
示例
#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
}
以下内容来自视频 Class Template Argument Deduction
自定义类模板中的应用
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
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>
}
C++17尝鲜:类模板中的模板参数自动推导的更多相关文章
- C++17尝鲜
https://cloud.tencent.com/developer/article/1351910 [译]C++17,optional, any, 和 variant 的更多细节 用户261520 ...
- [原创]java WEB学习笔记109:Spring学习---spring对JDBC的支持:使用 JdbcTemplate 查询数据库,简化 JDBC 模板查询,在 JDBC 模板中使用具名参数两种实现
本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...
- C++学习35 模板中的函数式参数
C++对模板类的支持比较灵活,模板类的参数中除了可以有类型参数,还可以有普通参数.例如: template<typename T, int N> class Demo{ }; N 是一个普 ...
- C++17尝鲜:变长 using 声明
using 声明 先来看 using 声明在类中的应用: 代码1 #include <iostream> using namespace std; struct A { void f(in ...
- VB类模块中属性的参数——VBA中Range对象的Value属性和Value2属性的一点区别
在VB中,属性是可以有参数的,而VBA中属性使用参数非常常见.比如最常用的:Worksheet.Range("A1:A10") VB的语法,使用参数的不一定是方法,也有可能是属性 ...
- C++17尝鲜:在 if 和 switch 语句中进行初始化
初始化语句 在C++17中,类似于 for 语句,在 if 和 switch 语句的判断条件之前也能加上初始化语句,语法形式如下: if (初始化语句; 条件) 语句 else 语句 switch ( ...
- C++17尝鲜:variant
variant variant 是 C++17 所提供的变体类型.variant<X, Y, Z> 是可存放 X, Y, Z 这三种类型数据的变体类型. 与C语言中传统的 union 类型 ...
- C++17尝鲜:编译期 if 语句
Constexpr If(编译期 if 语句) 以 if constexpr 打头的 if 语句被称为 Constexpr If. Constexpr If 是C++17所引入的新的语法特性.它为C+ ...
- C++17尝鲜:结构化绑定声明(Structured Binding Declaration)
结构化绑定声明 结构化绑定声明,是指在一次声明中同时引入多个变量,同时绑定初始化表达式的各个子对象的语法形式. 结构化绑定声明使用auto来声明多个变量,所有变量都必须用中括号括起来. cv-auto ...
随机推荐
- MyBatis持久层框架使用总结 转载
MyBatis持久层框架使用总结 MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google co ...
- thinkphp3.2用户登录ajax提交验证
html代码 <if condition="!isset($_SESSION['account'])"> <div class="load lf&quo ...
- 启动ECLIPSE时,提示failed to create the java virtual machine
修改eclipse.ini中的-XX:MaxPermSize=256M 这一项的原始值是512M.
- Redis高速内存缓冲平台可视化监控之RedisLive配置实战
一.引用 这两天在弄Reids高速缓存平台的图形化监控,由于对于Python并不是很熟悉,安装过程中遇到了不少问题,包括: 1.python必备安装包的安装问题 2.Redis Live界面显示问题 ...
- python给字典排序
应用场景: 统计一篇文章中单词的出现频率,然后进行排序 利用sorted函数,返回一个已经排序好的list,但不改变原来的数据结构 In [1]: dt = {'a':3,'b':2,'c':1} I ...
- python接口自动化20-requests获取响应时间(elapsed)与超时(timeout)
前言 requests发请求时,接口的响应时间,也是我们需要关注的一个点,如果响应时间太长,也是不合理的. 如果服务端没及时响应,也不能一直等着,可以设置一个timeout超时的时间 关于reques ...
- Linux 简单命令查询CPU、内存、网卡等信息
[转自]Linux查询CPU.内存.网卡等信息 看CPU信息(型号)# cat /proc/cpuinfo | grep name | cut -f2 -d: |uniq -c 1 Int ...
- 那些你希望N年前就掌握的命令
这篇文章转载自黑客志,短短的一篇文章我找到了3个对我非常有用的技巧,在信息爆炸的今天,简直就跟捡宝似的,希望这些命令对你也有帮助. 有人在Reddit上发帖询问:有没有哪条命令是你希望自己在几年前就掌 ...
- SQL Server 2012 OFFSET/FETCH NEXT分页示例
原文:http://beyondrelational.com/modules/29/presentations/483/scripts/12983/sql-server-2012-server-sid ...
- Oauth2.0(六):Resource Owner Password Credentials 授权和 Client Credentials 授权
这两种简称 Password 方式和 Client 方式吧,都只适用于应用是受信任的场景.一个典型的例子是同一个企业内部的不同产品要使用本企业的 Oauth2.0 体系.在有些情况下,产品希望能够定制 ...