c++11-type_traits类型萃取
Type_traits
type_traits类型选择功能,在一定的程度上,消除了if..else,switch-case。提供类型判断的功能。
c++11定义常量:
template<typename Type>
struct GetLeftSize::std::interal_constant<int,1>
{};
根据GetLeftSize::value来获取常量1;
类型判断的traits:
is_void
is_class
..........
is_const;
std::cout<<"int::"<<std::is_const<int>::value<<endl;
3.判断两个类型是否相同
is_baseof:判断两种类型是否为继承关系
is_convertible:判断前面的模版参数类型能否转换为后面的模版参数类型
4.类型转换的traits
struct remove_const;移除const
struct add_const;添加const
struct remove_reference移除引用
带有cv
template<typename T>
T* Create()
{
retrun new T();
}
int *P=Create<cosnt volatile int&>();----------》无法通过编译
template<typename T>
typename std::remove_cv<typename std::remove_refrence<T>::type>::type* Create()
{
typedef typename std::remove_cv<typename std::remove_reference<T>::type>::type U;
return new U();
}
std::decay是先移除引用,在移除cv符。
std::decay对于函数来说,是添加指针,可以将函数变为函数指针类型,然后保存起来。
template<typename F>
struct SimpleFunction{
using FnType=typename std::decacy<F>::type;
SimpleFunction(F& f):m_fn(f);
void Run(){
m_fn();
}
根据条件选择的traits
template<bool B, class T, class F>
struct conditional;
在std::conditional的模版参数,如果B为true,这conditional::type为T,否则为F。
获取可调用对象的返回类型traits
tempalte<class F, class ...ArgTypes>
class result_of<F(ArgTypes....)>
用来在编译期获取一个可调用的对象。
根据某些条件禁用或者启用某些类型的traits
std::enable_if,是的函数在判断条件B为true的情况下f才有有效。
template<class T>
typename std::enable_if<std::is_arithemtic<T>::value,T>::type foo(T t)
return t;
Optional的实现
optional<T> 对optional初始化之后,这个optional有效的,否则无效的。
作用:解决函数返回无效值的问题,如果查找不到对象,返回一个无效值,表明指向失败,返回一个未初始化的optional对象。
1.要内存对齐,调用place_new创建内存块,需要内存对齐,提高效率
2.多个参数有右值引用,和完美转发。
#pragma once
#include<type_traits>
template<typename T>
class MyOptional {
using data_t = typename std::aligned_storage<sizeof(T), std::alignment_of<T>::value>::type;
public:
MyOptional() {
}
MyOptional(const T& v) {
Create(v);
}
MyOptional(const MyOptional& other) {
if (other.IsInit())
Assign(other);
}
template<class... Args>
void Emplace(Args&&... args) {
Destory();
Create(std::forward<Args>(args)...);
}
bool IsInit() const {
return m_hasInit;
}
explicit operator bool() const {
return IsInit();
}
T const& operator*() const {
if (IsInit()) {
return *((T*)(&m_data));
}
throw std::logic_error("is not init");
}
private:
template<class... Args>
void Create(Args... args) {
new (&m_data) T(std::forward<Args>(args)...);
m_hasInit = true;
}
void Destory() {
if (m_hasInit)
{
m_hasInit = false;
((T*)&m_data)->~T();
}
}
void Assign(const MyOptional& other) {
if (other.IsInit()) {
Copy(other.m_data);
m_hasInit = true;
}
else {
Destory();
}
}
void Copy(const data_t& val) {
Destory();
new (&m_data) T(*(T*)&val);
}
private:
bool m_hasInit = false;
data_t m_data;
};
惰性求值
惰性求值,一般用于函数式的编程,表达式不在它被绑定到的变量后就立即求值,而是在后面的某个时候求值。
典型的应用场景是:当初始化某个对象的时,该对象创建需要较长的时间,同时也需要托管堆上分配较多的空间,初始化的时候变得很慢。
#pragma once
#include"optional.h"
#include<functional>
#include<memory>
template<typename T>
struct Lazy {
Lazy(){}
template<typename Func, typename... Args>
Lazy(Func&& f, Args && ... args) {
m_func = [&f, &args...] {
return f(args...);
};
}
T const & Value() {
if (!m_value.IsInit()) {
m_value = m_func();
}
return *m_value;
}
bool IsValueCreated() const {
return m_value.IsInit();
}
private:
std::function<T()> m_func;
MyOptional<T> m_value;
};
template<class Func, typename... Args>
Lazy<typename std::result_of<Func(Args...)>::type> lazy(Func &&func, Args&& ... args) {
return Lazy<typename std::result_of<Func(Args...)>::type>(std::forward<Func>(func), std::forward<Args>(args)...);
}
遇到的错误:记得如果定义了右值引用,一定要传递右值,否则,会造成异常。如果lazy方法,如果传递的时function<>,会造成求值的时候,找不到f。
dll帮助类
dll中,要定义一个对应的函数指针,接着调用GetProcAddress获取函数指针,最后调用该函数。
思路:
1.定义一个通用的指向函数,通过传递函数的名称和参数来调用
Ret CallDllFunc(const string& funcName, T arg);
2.通过函数名称,来获取一个范型的std::function来调用
解决两个问题:
1.函数的返回类型是多样的
2.函数的参数的类型和个数是多样的。
template<typename T>
std::function<T> GetFunction(const string& funcName){
auto it =m_map.find(funcName);
if(it==m_map.end())
auto addr=GetProcAddrss(m_hmod,funcName.c_str());
if(!addr)
return nullptr;
m_map.insert(std::make_pair(funcName,addr));
return std::function<T>((T*)(it->second));
}
template<typename T, typename... Args>
typename std::result_oof<std::function<T>(Args...)::type ExcuteFunc(const string& name, Args&& ... args)
auto f=GetFunction<T>(funcName);
return f(std::forward<Args(args));
lamada链式调用
它的原理是函数的指向结果,是一个的参数。
m_fn表示的上一个函数。
template<typename T>
class Task;
template<typename R, typename ... Args>
class Task<R(Args...)>
{
Task(std::function<R(Args..)> && f):m_fn(f){}
R run(Args&& ... args){
return m_fn(std::forward(args)...);
}
template<typename F>
auto Then(F&& f)->task<std::result_of(F(R))::type(args){
using return_type=typename std::result_of(F(R))::type;
auto func=std::move(m_fn);
return Task<return_type(Args...)>([func, f](Args&& ... args){
return f(func(std::forward<Args>(args)...));
});
}
private:
std::function(R(Args..)) m_fn;
}
Any类的实现
任何类型的值都可以赋值给它,进行类型擦除。Any可以容纳所有的数据类型,通过继承来擦除类型,基类不含模版参数,派生类才有模版参数,模版参数正式赋值的类型。
赋值:
把派生类的对象赋值给基类指针,基类只是原有数据的一个占位符,多态的隐士转换擦除了原始数据类型。
取值:
向下转换成派生类型来获取原始数据。
#pragma once
#include<memory>
#include<typeindex>
struct Any {
Any(void) :m_tpIndex(std::type_index(typeid(void))){}
Any(Any& that):m_ptr(that.Clone()),m_tpIndex(that.m_tpIndex){}
Any(Any&& that):m_ptr(std::move(that.m_ptr)),m_tpIndex(that.m_tpIndex){}
template<typename U, class = typename
std::enable_if<!std::is_same<typename std::decay<U>::type, Any>::value, U>::type>
Any(U&& value) : m_ptr(new Derived<typename std::decay<U>::type>(std::forward<U>(value))),
m_tpIndex(std::type_index(typeid(typename std::decay<U>::type))) {}
bool isNull() const {
return !bool(m_ptr);
}
template<class U> bool Is() const {
return m_tpIndex == std::type_index(typeid(U));
}
template<class U>
U& AnyCast(){
if (!Is<U>()) {
std::cout << "can not cast" << typeid(U).name() << "to " << m_tpIndex.name() << std::endl;
throw std::bad_cast();
}
auto derived = dynamic_cast<Derived<U>*> (m_ptr.get());
return derived->m_value;
}
Any& operator=(const Any& a) {
if (m_ptr == a.m_ptr)
return *this;
m_ptr = a.Clone();
m_tpIndex = a.m_tpIndex;
return *this;
}
private:
struct Base;
typedef std::unique_ptr<Base> BasePtr;
struct Base {
virtual ~Base(){}
virtual BasePtr Clone() const=0;
};
template<typename T>
struct Derived :Base {
template<typename U>
Derived(U && value) :m_value(std::forward<U>(value)){}
BasePtr Clone() const {
return BasePtr(new Derived<T>(m_value));
}
T m_value;
};
BasePtr Clone() const
{
if (m_ptr != nullptr) {
return m_ptr->Clone();
}
return nullptr;
}
BasePtr m_ptr;
std::type_index m_tpIndex;
};
Variant的实现
1.找出最大的typesize用来分配内存对齐的缓冲区
template<typename T, tyepname ... Args>
struct IntegerMax: std::interal_constant<int, (sizeof(T)>IntergerMax(Args...>::value?sizeof(T):IntegerMax<Args...>::value)>();
IntergerMax<Types....>::value;
对齐大小:
template<typename...Args>
struct MaxAlign:std::intergral_constant<int, IntegerMax<std::alignment_of<Args>::value...>::value>{}
2.类型检查和缓冲区中创建对象
template<typename T, typename... List>
struct Contains : std::true_type{};
template <typename T, typename Head, typename... Rest>
struct Contains<T, Head, Rest...>
:std::conditional< std::is_same<T, Head>::value, std::true_type,
Contains<T, Rest...>>::type();
通过bool值,contains<T,Types>::value可以判断是否包含某种类型。
3.缓冲区上创建对象
new(data) T(value)
function_traits
其主要的作用是获取所有的函数语义的函数类型,返回类型,参数个数和参数的具体类型。
如:
int func(int a,string b);
function_traits<decltype(func)>::function_type;//int _cdecl(int,string);
function_traits<decltype(func)>::return_type;//int
function_traits<decltype(func)>::arity;//2
function_traits<decltype(func)>::arg_type<0>; //获取第一个参数的类型,int
实现function_tratis的关键技术
实现function_traits关键是通过模版特化和可变参数模版来获取函数的类型和返回类型。
template<typename T>
struct function_traits;
在通过特化,将返回类型和可变参数作为模版参数,可以获取函数的类型,返回值和参数的个数。
#pragma once
#include<functional>
#include<tuple>
template<typename T>
struct function_traits;
template<typename Ret,typename... Args>
struct function_traits<Ret(Args...)>
{
public:
enum {arity=sizeof...(Args) };
typedef Ret function_type(Args...);
typedef Ret return_type;
using stl_function_type = std::function<function_type>;
typedef Ret(*pointer)(Args...);
template<size_t I>
struct args {
static_assert(I < arity, "index is out of range");
using type = typename std::tuple_element < I, std::tuple<Args...>>::type;
};
};
template<typename Ret, typename... Args>
struct function_traits<Ret(*)(Args...)>:function_traits<Ret(Args...)>
{
};
template<typename Ret, typename... Args>
struct function_traits<std::function<Ret(Args...)>> :function_traits<Ret(Args...)>
{
};
#define FUNCTION_TRAITS(...)\
template<typename ReturnType, typename ClassType, typename ... Args>\
struct function_traits<ReturnType(ClassType::*)(Args...)>:function_traits<ReturnType(Args...)>{ };\
FUNCTION_TRAITS()
/*
FUNCTION_TRAITS(const)
FUNCTION_TRAITS(volatile)
FUNCTION_TRAITS(const volatile)*/
template<typename Callable>
struct function_traits :function_traits<decltype(&Callable::operator())> {};
template<typename Function>
typename function_traits<Function>::stl_function_type to_function(const Function & lambda) {
return static_cast<typename function_traits<Function>::stl_function_type>(lambda);
}
template<typename Function>
typename function_traits<Function>::stl_function_type to_function(const Function && lambda) {
return static_cast<typename function_traits<Function>::stl_function_type>(std::forward<Function>(lambda));
}
template<typename Function>
typename function_traits<Function>::pointer to_function(const Function & lambda) {
return static_cast<typename function_traits<Function>::pointer>((lambda));
}
c++11-type_traits类型萃取相关推荐
- type_traits 类型萃取
一. c++ traits traits是c++模板编程中使用的一种技术,主要功能: 把功能相同而参数不同的函数抽象出来,通过traits将不同的参数的相同属性提取出来,在函数中利用这些用traits ...
- C++类型萃取之type_traits和type_info
类型萃取 类型判断 typeid decltype和declval enable_if 类型萃取 通过type_traits可以实现在编译期计算.查询.判断.转换和选择,增强了泛型编程的能力,也增强了 ...
- C++的类型萃取技术
http://www.cppblog.com/nacci/archive/2005/11/03/911.aspx?spm=0.0.0.0.iyJqvt&file=911.aspx 自从C++中 ...
- C++特化的应用——类型萃取
提出问题:如何实现一个对于拷贝内置类型和自定义类型通用的拷贝函数? 1.拷贝内置类型 对于内置类型我们可以用memcpy进行拷贝,因为memcpy属于浅拷贝,内置类型不涉及资源管理的问题. 2.拷贝自 ...
- C/Cpp / STL / 类型萃取
作用 类型萃取使用模板技术来萃取类型(包含自定义类型和内置类型)的某些特性,用以判断该类型是否含有某些特性,从而在泛型算法中来对该类型进行特殊的处理用来达到提高效率或者其他的目的. 类型萃取的实现的基 ...
- C++ 模板类型萃取技术 traits
当函数,类或者一些封装的通用算法中的某些部分会因为数据类型不同而导致处理或逻辑不同(而我们又不希望因为数据类型的差异而修改算法本身的封装时),traits会是一种很好的解决方案.(类型测试发生在编译期 ...
- C++之类型萃取技巧
使用类型萃取的原因 就是当你的顺序表是自定义类型,我们进行顺序表增容的时候,这个时候会出现一个问题,比如string类型,这个类型中有一个_buf与_ptr,当储存少于16个的时候这时会储存在_buf ...
- [c++]——什么是类型萃取
类型萃取 类型萃取从字面意思上来说其实就是帮助我们挑选某个对象的类型,筛选特定的对象来做特定的事. C++中的类型萃取并不是每个人都熟知,他们一般都出现在STL库底层的实现原理中,和笔者一样,相信听到 ...
- C++ — 类型萃取
类型萃取 在编程中我们可能时常会听到类型萃取这个高大上的"学术名词",我们今天来探究一下这个高大上的学术名词 到底是何方神圣,先看看官方的解释类型萃取使用模板技术来萃取类型(包含自 ...
- C++模板编程之类型萃取 惊鸿一瞥
一.从模板函数std::distance(计算迭代器的距离)开始 #include <iostream> #include <vector> #include <list ...
最新文章
- android 手写字体识别,一种基于Android系统的手写数学公式识别及生成MathML的方法...
- 第02期 基础算法(Leetcode)刻意练习开营计划
- ajax 请求svg,jQuery append 到AJAX加载的SVG问题
- 【BZOJ4515】游戏,树链剖分+永久化标记线段树维护线段信息(李超线段树)
- 超融合架构的优缺点_知道 超融合基础架构吗
- POJ 1611 The Suspects(简单并查集)
- Qt5调用Snap7
- Java SSM框架简介
- 大数据经典书籍良心推荐
- Externally added files can be added to Git
- Android wifi PNO扫描流程(Andriod O)
- Android 9 wifi PNO 扫描
- thinkphp6学习教程与源码 tp6开源CMS系统源码研究
- 一文读懂电磁学发展史[图文版]
- vmm_xactor
- 格斗机器人制造图纸_轮式格斗机器人的制作方法
- vue.js毕业设计,基于vue.js前后端分离订座预约系统设计与实现(H5移动项目)
- 图说大型网站的技术架构
- 【Linux】之 Linux 性能监控工具
- 计算机动画算法与编程基础pdf,清华大学 计算机动画算法与编程基础2-图形绘制课件.ppt...
热门文章
- 【数据结构与算法】之深入解析“根据身高重建队列”的求解思路与算法示例
- 【数据结构与算法】之深入解析“逆波兰表达式求值”的求解思路与算法示例
- 实现iOS App的在线安装
- 面试题 02.01. 移除重复节点
- 数据解析,重中之重!
- 征战蓝桥 —— 2014年第五届 —— C/C++A组第1题——猜年龄
- 《算法竞赛入门经典》 例题5-2 木块问题(The Blocks Problem,UVa 101)
- 【IT资讯】编程语言面临重新洗牌,这六种要凉凉
- samba 实现不同操作系统之间的文件共享
- 每天一道LeetCode-----比较两个字符串,每个字符串被若干'.'分成多个数字,一个个比较