c++11-type_traits类型萃取
Type_traits
type_traits類型選擇功能,在一定的程度上,消除了if..else,switch-case。提供類型判斷的功能。
c++11定義常量:
template<typename Type>
struct GetLeftSize::std::interal_constant<int,1>
{};
根據(jù)GetLeftSize::value來獲取常量1;
類型判斷的traits:
is_void
is_class
..........
is_const;
std::cout<<"int::"<<std::is_const<int>::value<<endl;
3.判斷兩個類型是否相同
is_baseof:判斷兩種類型是否為繼承關(guān)系
is_convertible:判斷前面的模版參數(shù)類型能否轉(zhuǎn)換為后面的模版參數(shù)類型
4.類型轉(zhuǎn)換的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對于函數(shù)來說,是添加指針,可以將函數(shù)變?yōu)楹瘮?shù)指針類型,然后保存起來。
template<typename F>
struct SimpleFunction{
using FnType=typename std::decacy<F>::type;
SimpleFunction(F& f):m_fn(f);
void Run(){
m_fn();
}
根據(jù)條件選擇的traits
template<bool B, class T, class F>
struct conditional;
在std::conditional的模版參數(shù),如果B為true,這conditional::type為T,否則為F。
獲取可調(diào)用對象的返回類型traits
tempalte<class F, class ...ArgTypes>
class result_of<F(ArgTypes....)>
用來在編譯期獲取一個可調(diào)用的對象。
根據(jù)某些條件禁用或者啟用某些類型的traits
std::enable_if,是的函數(shù)在判斷條件B為true的情況下f才有有效。
template<class T>
typename std::enable_if<std::is_arithemtic<T>::value,T>::type foo(T t)
? ?return t;
Optional的實現(xiàn)
optional<T> 對optional初始化之后,這個optional有效的,否則無效的。
作用:解決函數(shù)返回?zé)o效值的問題,如果查找不到對象,返回一個無效值,表明指向失敗,返回一個未初始化的optional對象。
1.要內(nèi)存對齊,調(diào)用place_new創(chuàng)建內(nèi)存塊,需要內(nèi)存對齊,提高效率
2.多個參數(shù)有右值引用,和完美轉(zhuǎn)發(fā)。
#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;
};
惰性求值
惰性求值,一般用于函數(shù)式的編程,表達式不在它被綁定到的變量后就立即求值,而是在后面的某個時候求值。
典型的應(yīng)用場景是:當(dāng)初始化某個對象的時,該對象創(chuàng)建需要較長的時間,同時也需要托管堆上分配較多的空間,初始化的時候變得很慢。
#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中,要定義一個對應(yīng)的函數(shù)指針,接著調(diào)用GetProcAddress獲取函數(shù)指針,最后調(diào)用該函數(shù)。
思路:
1.定義一個通用的指向函數(shù),通過傳遞函數(shù)的名稱和參數(shù)來調(diào)用
Ret CallDllFunc(const string& funcName, T arg);
2.通過函數(shù)名稱,來獲取一個范型的std::function來調(diào)用
解決兩個問題:
1.函數(shù)的返回類型是多樣的
2.函數(shù)的參數(shù)的類型和個數(shù)是多樣的。
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鏈?zhǔn)秸{(diào)用
它的原理是函數(shù)的指向結(jié)果,是一個的參數(shù)。
m_fn表示的上一個函數(shù)。
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類的實現(xiàn)
任何類型的值都可以賦值給它,進行類型擦除。Any可以容納所有的數(shù)據(jù)類型,通過繼承來擦除類型,基類不含模版參數(shù),派生類才有模版參數(shù),模版參數(shù)正式賦值的類型。
賦值:
把派生類的對象賦值給基類指針,基類只是原有數(shù)據(jù)的一個占位符,多態(tài)的隱士轉(zhuǎn)換擦除了原始數(shù)據(jù)類型。
取值:
向下轉(zhuǎn)換成派生類型來獲取原始數(shù)據(jù)。
#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的實現(xiàn)
1.找出最大的typesize用來分配內(nèi)存對齊的緩沖區(qū)
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.類型檢查和緩沖區(qū)中創(chuàng)建對象
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.緩沖區(qū)上創(chuàng)建對象
new(data) T(value)
?
function_traits
其主要的作用是獲取所有的函數(shù)語義的函數(shù)類型,返回類型,參數(shù)個數(shù)和參數(shù)的具體類型。
如:
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>; //獲取第一個參數(shù)的類型,int
實現(xiàn)function_tratis的關(guān)鍵技術(shù)
實現(xiàn)function_traits關(guān)鍵是通過模版特化和可變參數(shù)模版來獲取函數(shù)的類型和返回類型。
template<typename T>
struct function_traits;
在通過特化,將返回類型和可變參數(shù)作為模版參數(shù),可以獲取函數(shù)的類型,返回值和參數(shù)的個數(shù)。
#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));
}
?
?
總結(jié)
以上是生活随笔為你收集整理的c++11-type_traits类型萃取的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: c++11-std::functionb
- 下一篇: c++11 多线程