c++11-type_traits类型萃取

Type_traits

type_traits类型选择功能,在一定的程度上,消除了if..else,switch-case。提供类型判断的功能。

c++11定义常量:

template

struct GetLeftSize::std::interal_constant

{};

根据GetLeftSize::value来获取常量1;

类型判断的traits:

is_void

is_class

..........

is_const;

std::cout<<"int::"<::value<

3.判断两个类型是否相同

is_baseof:判断两种类型是否为继承关系

is_convertible:判断前面的模版参数类型能否转换为后面的模版参数类型

4.类型转换的traits

struct remove_const;移除const

struct add_const;添加const

struct remove_reference移除引用

 

带有cv

template

T* Create()

{

    retrun new T();

}

int *P=Create();----------》无法通过编译

template

typename std::remove_cv::type>::type* Create()

{

  typedef typename std::remove_cv::type>::type U;

  return new U();

}

std::decay是先移除引用,在移除cv符。

std::decay对于函数来说,是添加指针,可以将函数变为函数指针类型,然后保存起来。

template

struct SimpleFunction{

using FnType=typename std::decacy::type;

SimpleFunction(F& f):m_fn(f);

void Run(){

m_fn();

}

根据条件选择的traits

template

struct conditional;

在std::conditional的模版参数,如果B为true,这conditional::type为T,否则为F。

获取可调用对象的返回类型traits

tempalte

class result_of

用来在编译期获取一个可调用的对象。

根据某些条件禁用或者启用某些类型的traits

std::enable_if,是的函数在判断条件B为true的情况下f才有有效。

template

typename std::enable_if::value,T>::type foo(T t)

   return t;

Optional的实现

optional 对optional初始化之后,这个optional有效的,否则无效的。

作用:解决函数返回无效值的问题,如果查找不到对象,返回一个无效值,表明指向失败,返回一个未初始化的optional对象。

1.要内存对齐,调用place_new创建内存块,需要内存对齐,提高效率

2.多个参数有右值引用,和完美转发。

#pragma once
#include

template
class MyOptional {
    using data_t = typename std::aligned_storage::value>::type;
public:
    MyOptional() {

    }
    MyOptional(const T& v) {
        Create(v);
    }
    MyOptional(const MyOptional& other) {
        if (other.IsInit())
            Assign(other);
    }
    template
    void Emplace(Args&&... args) {
        Destory();
        Create(std::forward(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
    void Create(Args... args) {
        new (&m_data) T(std::forward(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
#include
template
struct Lazy {
    Lazy(){}

    template
    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 m_func;
    MyOptional m_value;
};
template
Lazy::type> lazy(Func &&func, Args&& ... args) {
    return Lazy::type>(std::forward(func), std::forward(args)...);
}
 

遇到的错误:记得如果定义了右值引用,一定要传递右值,否则,会造成异常。如果lazy方法,如果传递的时function<>,会造成求值的时候,找不到f。

 

dll帮助类

dll中,要定义一个对应的函数指针,接着调用GetProcAddress获取函数指针,最后调用该函数。

思路:

1.定义一个通用的指向函数,通过传递函数的名称和参数来调用

Ret CallDllFunc(const string& funcName, T arg);

2.通过函数名称,来获取一个范型的std::function来调用

解决两个问题:

1.函数的返回类型是多样的

2.函数的参数的类型和个数是多样的。

template

std::function 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*)(it->second));

}

 

template

typename std::result_oof(Args...)::type ExcuteFunc(const string& name, Args&& ... args)

 auto f=GetFunction(funcName);

return f(std::forward

 

lamada链式调用

它的原理是函数的指向结果,是一个的参数。

m_fn表示的上一个函数。

template

class Task;

template

class Task

{

   Task(std::function && f):m_fn(f){}

  R run(Args&& ... args){

             return m_fn(std::forward(args)...);

}

template

auto Then(F&& f)->task

using return_type=typename std::result_of(F(R))::type;

auto func=std::move(m_fn);

return Task([func, f](Args&& ... args){

    return f(func(std::forward(args)...));

});

}

private:

      std::function(R(Args..)) m_fn;

}

 

Any类的实现

任何类型的值都可以赋值给它,进行类型擦除。Any可以容纳所有的数据类型,通过继承来擦除类型,基类不含模版参数,派生类才有模版参数,模版参数正式赋值的类型。

赋值:

把派生类的对象赋值给基类指针,基类只是原有数据的一个占位符,多态的隐士转换擦除了原始数据类型。

取值:

向下转换成派生类型来获取原始数据。

#pragma once
#include
#include
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         std::enable_if::type, Any>::value, U>::type> 
        Any(U&& value) : m_ptr(new Derived::type>(std::forward(value))),
            m_tpIndex(std::type_index(typeid(typename std::decay::type))) {}

    bool isNull() const {
        return !bool(m_ptr);
    }
    template bool Is() const {
        return m_tpIndex == std::type_index(typeid(U));
    }

    template
    U& AnyCast(){
        if (!Is()) {
            std::cout << "can not cast" << typeid(U).name() << "to " << m_tpIndex.name() << std::endl;
            throw std::bad_cast();
        }
        auto derived = dynamic_cast*> (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 BasePtr;

    struct Base {
        virtual ~Base(){}
        virtual BasePtr Clone() const=0;
    };
    template
    struct Derived :Base {
        template
        Derived(U && value) :m_value(std::forward(value)){}
        BasePtr Clone() const {
            return BasePtr(new Derived(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

struct IntegerMax: std::interal_constantIntergerMax(Args...>::value?sizeof(T):IntegerMax::value)>();

IntergerMax::value;

对齐大小:

template

struct MaxAlign:std::intergral_constant::value...>::value>{}

2.类型检查和缓冲区中创建对象

template

struct Contains : std::true_type{};

 

template

struct Contains

:std::conditional< std::is_same::value, std::true_type,

Contains>::type();

通过bool值,contains::value可以判断是否包含某种类型。

3.缓冲区上创建对象

new(data) T(value)

 

function_traits

其主要的作用是获取所有的函数语义的函数类型,返回类型,参数个数和参数的具体类型。

如:

int func(int a,string b);

function_traits::function_type;//int _cdecl(int,string);

function_traits::return_type;//int

function_traits::arity;//2

function_traits::arg_type<0>; //获取第一个参数的类型,int

实现function_tratis的关键技术

实现function_traits关键是通过模版特化和可变参数模版来获取函数的类型和返回类型。

template

struct function_traits;

在通过特化,将返回类型和可变参数作为模版参数,可以获取函数的类型,返回值和参数的个数。

#pragma once
#include
#include

template
struct function_traits;

template
struct function_traits
{
public:
    enum {arity=sizeof...(Args) };
    typedef Ret function_type(Args...);
    typedef Ret return_type;

    using stl_function_type = std::function;

    typedef Ret(*pointer)(Args...);

    template
    struct args {
        static_assert(I < arity, "index is out of range");
        using type = typename std::tuple_element < I, std::tuple>::type;
    };
};
template
struct function_traits:function_traits
{

};
template
struct function_traits> :function_traits
{

};

#define FUNCTION_TRAITS(...)\
template\
struct function_traits:function_traits{ };\

FUNCTION_TRAITS()
/*
FUNCTION_TRAITS(const)
FUNCTION_TRAITS(volatile)
FUNCTION_TRAITS(const volatile)*/

template
struct function_traits :function_traits {};

template
typename function_traits::stl_function_type to_function(const Function & lambda) {
    return static_cast::stl_function_type>(lambda);
}

template
typename function_traits::stl_function_type to_function(const Function && lambda) {
    return static_cast::stl_function_type>(std::forward(lambda));
}

template
typename function_traits::pointer to_function(const Function & lambda) {
    return static_cast::pointer>((lambda));
}


 

 

你可能感兴趣的:(C++_C++11_STL)