第17课 类型萃取(1)_基本的type_traits
1. type_traits类型萃取
(1)type_traits通过定义一些结构体或类,并利用模板类特化和偏特化的能力,给类型赋予一些特性,这些特性根据类型的不同而异。在程序设计中可以使用这些traits来判断一个类型的一些特性,引发C++的函数重载机制,实现同一种操作因类型不同而异的效果。
(2)type_traits提供了丰富的编译期计算、查询、判断、转换和选择的帮助类。
(3)type_traits的类型选择功能,在一定程序上可以消除冗长的switch-cast或if-else的语句。提高代码可维护性。type_traits的类型判断功能,在编译期可以检查出是否是正确的类型,以能编写更安全的代码。
【实例分析】部分类型萃取的实现(类模板)
//#include <iostream>
//using namespace std;
/*********************const/volatile************************/
//remove const
template<typename _Tp> //泛化
struct remove_const
{
typedef _Tp type;
}; template<typename _Tp>
struct remove_const<_Tp const> //特化
{
typedef _Tp type;
}; //remove_volatile
template<typename _Tp> //泛化
struct remove_volatile
{
typedef _Tp type;
}; template<typename _Tp>
struct remove_volatile<_Tp volatile> //特化
{
typedef _Tp type;
}; //remove_cv
template<typename _Tp>
struct remove_cv
{
typedef typename
remove_const<typename remove_volatile<_Tp>::type>::type type;
}; //add_const
template<typename _Tp>
struct add_const
{
typedef _Tp const type;
}; /***********************integral_constant*************************/
//常量包装类型
template <class T, T v>
struct integral_constant
{
static const T value = v;
typedef T value_type;
typedef integral_constant<T, v> type;
}; //定义true和false两个类型
typedef integral_constant<bool, true> true_type;
typedef integral_constant<bool, false> false_type; template<typename> //泛化
struct __is_void_helper : public false_type{}; template<> //特化
struct __is_void_helper<void> : public true_type{}; //is_void
template<typename _Tp>
struct is_void : public __is_void_helper<typename remove_cv<_Tp>::type>::type{}; /***********************integral*************************/
template<typename> //泛化
struct __is_integral_helper : public false_type{}; template<> //特化: bool是intergal类型
struct __is_integral_helper<bool> : public true_type{}; template<> //特化: char是intergal类型
struct __is_integral_helper<char> : public true_type{}; template<> //特化: int是intergal类型
struct __is_integral_helper<int> : public true_type{}; template<> //特化: usigned long long是intergal类型
struct __is_integral_helper<unsigned long long> : public true_type{}; //... //is_integral
template<typename _Tp>
struct is_integral : public __is_integral_helper<typename remove_cv<_Tp>::type>::type{}; //is_const
template <class _Tp>
struct is_const : public integral_constant<bool, false> {}; template <class _Tp>
struct is_const<_Tp const> : public integral_constant<bool, true> {}; /********************enum/class/union**********************/
//is_enum 注意:__is_enum是编译器内置类型
template<typename _Tp>
struct is_enum : public integral_constant<bool, __is_enum(_Tp)>{}; //is_union 注意:__is_union是编译器内置类型
template<typename _Tp>
struct is_union : public integral_constant<bool, __is_union(_Tp)>{}; //is_class 注意:__is_class是编译器内置类型
template<typename _Tp>
struct is_class : public integral_constant<bool, __is_class(_Tp)>{}; //is_pod: 注意:__is_pod是编译器内置类型
template<typename _Tp>
struct is_pod : public integral_constant<bool, __is_pod(_Tp)>{}; int main()
{
return ;
}
2. 类型判断
(1)基本类型(类模板:判断T是否是相应的类型)
①is_void、is_integral、is_array、is_floating_point(浮点)、 is_pointer
②is_enum、is_union、is_class
③is_lvalue_reference、is_rvalue_reference
④is_function、is_member_object_pointer(成员对象指针)、is_member_function_pointer(成员函数指针)
(2)复合类型(类模板)
①is_fundamental:是否是整型、浮点、void或null_ptr类型。
②is_arithemetic:是否是整型和浮点类型
③is_scalar:是否是arithemetic、enumeration、pointer、pointer to member或std::nullptr_t类型。
④is_object:是否为对象类型(不是函数、引用或void)
⑤is_compound:是否非fundamental类型构造的
⑥is_reference:是否为引用(含左值引用和右值引用)
⑦is_member_pointer:是否是成员指针(即非静态成员对象或函数的指针)
(3)类型的属性
①is_const、is_volatile、is_literal_type、is_signed、is_unsigned。
②is_trivial、is_trivially_copyable、is_standart_layout(标准内存布局,一般用于跨语言的兼容)、is_pod、is_empty(空类)
③is_polymorphic(是否有虚函数)、is_abstract(是否是抽象类)
3. 两个类型之间的关系
(1)is_same<T, U>: T和U的类型是否相同
(2)is_base_of<Base, Derived>:Base是否为Derived类型的基类
(3)is_convertible<From, To>:From是否能转为To模板参数类型。
【编程实验】基本type_traits和判断两个类型之间的关系
#include <iostream>
using namespace std;
class Parent{};
class Child : public Parent{}; //class Child : Parent{},为private继承
class Alone{};
int main()
{
cout << std::boolalpha; //以下的0、1按false和true格式输出
/*基本的type_traits用法*/
cout << is_const<int>::value << endl; //false
cout << is_const<const int>::value << endl; //true
cout << is_const<const int&>::value << endl; //false
cout << is_const<const int*>::value << endl; //false
cout << is_const<int* const>::value << endl; //true
/*is_same用法*/
cout << is_same<int, int>::value << endl; //true
cout << is_same<int, unsigned int>::value << endl;//false
cout << is_same<int, signed int>:: value << endl; //true
/*is_base_of*/
cout << is_base_of<Parent, Child>:: value << endl; //true
cout << is_base_of<Child, Parent>:: value << endl; //false
cout << is_base_of<Parent, Alone>:: value << endl; //false
/*is_convertible<From, To>用法:判断From类型是否可以转为To类型*/
cout << is_convertible<Parent*, Child*>:: value << endl; //false
cout << is_convertible<Child*, Parent*>:: value << endl; //true
cout << is_convertible<Parent*, Alone*>:: value << endl; //false
return ;
}
4. 类型转换traits
(1)const-volatile限定符
①remove_cv<T>、remove_const<T>、remove_volatile<T>
②add_cv<T>、add_const<T>、add_volatile<T>
(2)引用: remove_reference<T>、add_lvalue_reference<T>、add_rlvalue_reference。
(3)指针: remove_pointer<T>、add_pointer<T>
(4)数组:remove_extent<T>移除数组顶层维度、remove_all_extents<T>移除所有维度。
(5)其它
①decay<T>:类型退化,主要用移除引用、cv符及为函数或数组添加指针。其转换规则如下。
A.先移除T的类型引用,得到类型U,U定义为remove_reference<T>::type。
B.如果is_array<U>::value为true,最终转换为remove_extent<U>::type*。
C.否则,如果is_function<U>::value为true,转换为add_pointer<U>::type。
D.否则,转换为remove_cv<U>::type。
②common_type<T1, T2, T3…>:获取公共类型
【编程实验】类型转换traits
#include <iostream>
#include <memory> using namespace std;
//类型转换type_traits //根据模板参数类创建对象时,要注意移除cv和引用
template<typename T>
class Test
{
//typedef typename std::remove_cv<typename std::remove_reference<T>::type>::type U; //移除可能的引用和cv
//以上的等价写法
typedef typename std::decay<T>::type U; //先移除T的引用,再移除cv符, std::unique_ptr<U> m_ptr; //m_ptr智能指针 public:
Test(): m_ptr(new U){} //创建智能指针时,需要获取T的原始类型 typename std::add_lvalue_reference<U>::type //返回值类型,添加左值引用
get() const
{
return *m_ptr.get();
}
}; //利用std::decay保存函数指针
template<typename T>
class Sample
{
using FnType = typename std::decay<T>::type; //为函数添加指针
FnType m_fn;
public:
Sample(T& f) : m_fn(f){}; void run()
{
m_fn();
}
}; void func()
{
cout <<"void func()" << endl;
} int main()
{
cout << std::boolalpha; //以下的0、1按false和true格式输出 //添加和移除const、reference
cout <<is_same<const int, add_const<int>::type>::value << endl; //true
cout <<is_same<int, remove_const<const int>::type>::value << endl; //true
cout <<is_same<int&, add_lvalue_reference<int>::type>::value << endl; //true
cout <<is_same<int&&,add_rvalue_reference<int>::type>::value << endl; //true
cout <<is_same<int, remove_reference<int&>::type>::value << endl; //true
cout <<is_same<int, remove_reference<int&&>::type>::value << endl; //true cout <<is_same<int*, add_pointer<int>::type>::value << endl; //true //移除数组顶层维度
cout <<is_same<int, remove_extent<int[]>::type>::value << endl; //true
cout <<is_same<int[], remove_extent<int[][]>::type>::value << endl; //true
cout <<is_same<int[][], remove_extent<int[][][]>::type>::value << endl; //true
cout <<is_same<int, remove_all_extents<int[][][]>::type>::value << endl; //true,移除所有维度 //取公共类型
typedef common_type<unsigned char, short, int>::type NumericType;
cout <<is_same<int, NumericType>::value << endl; //true //测试Test类
Test<const int&> t; //T类型故意传入带cv和引用,Test类部在创建对象时,需去除这些属性
int a = t.get();
cout << a << endl; //std::decay
cout <<is_same<int, decay<int>::type>::value << endl; //true
cout <<is_same<int, decay<int&&>::type>::value << endl; //true,移除引用
cout <<is_same<int, decay<const int&>::type>::value << endl; //true,移除cv和引用
cout <<is_same<int*, decay<int[]>::type>::value << endl; //true,移除数组顶层维度
cout <<is_same<int(*)(int), decay<int(int)>::type>::value << endl; //true,将函数变为函数指针 Sample<decltype(func)> s(func);
s.run(); //void func(); return ;
}
第17课 类型萃取(1)_基本的type_traits的更多相关文章
- 第18课 类型萃取(2)_获取返回值类型的traits
1. 获取可调用对象返回类型 (1)decltype:获取变量或表达式的类型(见第2课) (2)declval及原型 ①原型:template<class T> T&& d ...
- 第19课 类型萃取(3)_类型选择的traits
1. std::conditional (1)原型:template <bool Cond, class T, class F> struct conditional; //根据条件获取T ...
- STL的迭代器和类型萃取
今天就可以把STL库中迭代器的实现,和类型萃取好好整理一下了 迭代器的设计思维是STL的关键所在,在STL的实际运用和泛型思维,迭代器都扮演着十分重要的角色,STL力求把数据容器和算法的概念分开来,于 ...
- 头一回发博客,来分享个有关C++类型萃取的编写技巧
废话不多说,上来贴代码最实在,哈哈! 以下代码量有点多,不过这都是在下一手一手敲出来的,小巧好用,把以下代码复制出来,放到相应的hpp文件即可,VS,GCC下均能编译通过 #include<io ...
- C++的类型萃取技术
应该说,迭代器就是一种智能指针,因此,它也就拥有了一般指针的所有特点——能够对其进行*和->操作.但是在遍历容器的时候,不可避免的要对遍历的容器内部有所了解,所以,设计一个迭代器也就自然而然的变 ...
- 类型萃取(type traits)
1. 类型萃取的作用 类型萃取使用模板技术来萃取类型(包含自定义类型和内置类型)的某些特性,用以判断该类型是否含有某些特性,从而在泛型算法中来对该类型进行特殊的处理用来提高效率或者其他.例如:在STL ...
- C++类型萃取
stl中的迭代器和C++中的类型萃取: http://www.itnose.net/detail/6487058.html 赐教!
- c++11——type_traits 类型萃取
一. c++ traits traits是c++模板编程中使用的一种技术,主要功能: 把功能相同而参数不同的函数抽象出来,通过traits将不同的参数的相同属性提取出来,在函数中利用这些用tr ...
- 【C++】模板简述(五):类型萃取
功能 类型萃取,在STL中用到的比较多,用于判断一个变量是否为POD类型. 简述来说可以用来判断出某个变量是内置类型还是自定义类型. 通过类型萃取,萃取到变量类型,对不同变量进行不同处理,可以提升程序 ...
随机推荐
- Wireshark 过滤 基本语法
转载 1.过滤IP,如来源IP或者目标IP等于某个IP 例子: ip.src eq 192.168.1.107 or ip.dst eq 192.168.1.107 或者 ip.addr eq 1 ...
- 学习笔记——SM2算法原理及实现
RSA算法的危机在于其存在亚指数算法,对ECC算法而言一般没有亚指数攻击算法 SM2椭圆曲线公钥密码算法:我国自主知识产权的商用密码算法,是ECC(Elliptic Curve Cryptosyste ...
- Saiku更改源代码实现默认查询一天的数据(十)
Saiku通过更改源代码实现默认查询前一天数据 saiku在本地进行的编译的方式前面已有教程说明,接下来就是更改原代码了 (从网上学得教程,目前只了解到获取最新一天的数据信息) 参考博客地址: htt ...
- 2018-北航-面向对象-前三次OO作业分析与小结
基于度量的程序结构分析 由于平时使用了NetBrains出品的IDEA作为IDE,在分析程序的时候我使用了IDEA的插件Metrics Reloaded.然而在使用时发现不懂得很多分析项目的含义,因此 ...
- 剑指Offer 29. 最小的K个数 (其他)
题目描述 输入n个整数,找出其中最小的K个数.例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4. 题目地址 https://www.nowcoder.com/prac ...
- windows 安装mysql 5.7的正确姿势
1.首先上MySql的官网下载 https://dev.mysql.com/downloads/mysql/ 2. 以我所选版本为例(免安装版),选择MYSQL Community Server 然 ...
- Js 基本类型和引用类型
一个变量可以存放两种类型的值,基本类型的值(primitive values)和引用类型的值(reference values). ES6 引入了一种新的原始数据类型 Symbol,表示独一无二的值. ...
- servlet编程操作
所谓servlet指:服务器处理来自Web浏览器或其他客户端的HTTP请求的服务器程序.客户端向服务器发送Http请求,经Tomcat封装处理转给Servlet容器,Servlet容器在把请求或回应交 ...
- springboot中get post put delete 请求
组合注解(RequestMapping的变形) @GetMapping = @RequestMapping(method = RequestMethod.GET) @PostMapping = @Re ...
- .net调用系统软键盘(兼容win7及win10)
没有什么技术说明,也是查询出来的,在此做记录 public class StartKeyBoard { public static bool isShowNumBoard = fa ...