c++模板——萃取

1 转换萃取

实现std提供的标准库

1.1 删除引用——std::remove_reference<>

template<typename T>
struct RemoveReferenceT
{
    using type = T;
};

template<typename T>
struct RemoveReferenceT<T&>
{
    using type = T;
};

template<typename T>
struct RemoveReferenceT<T&&>
{
    using type = T;
};

template<typename T>
using RemoveReference = typename RemoveReferenceT<T>::type;

1.2 添加引用(添加左值引用std::add_lvalue_reference<>和右值引用std::add_rvalue_reference<>)

//=================添加左值引用实现部分===============
template<typename T>
struct AddLValueReferenceT
{
    using type = T&;
};
template<>
struct AddLValueReferenceT<void>
{
    using type = void;
};
template<>
struct AddLValueReferenceT<void const>
{
    using type = void const;
};
template<>
struct AddLValueReferenceT<void volatile>
{
    using type = void volatile;
};
template<>
struct AddLValueReferenceT<void volatile const>
{
    using type = void volatile const;
};

template<typename T>
using AddLValueReference = typename AddLValueReferenceT<T>::type;

//=================添加右值引用实现部分===============
template<typename T>
struct AddRValueReferenceT
{
    using type = T&&;
};
template<>
struct AddRValueReferenceT<void>
{
    using type = void;
};
template<>
struct AddRValueReferenceT<void const>
{
    using type = void const;
};
template<>
struct AddRValueReferenceT<void volatile>
{
    using type = void volatile;
};
template<>
struct AddRValueReferenceT<void volatile const>
{
    using type = void volatile const;
};

template<typename T>
using AddRValueReference = typename AddRValueReferenceT<T>::type;

int main(int argc, char ** argv)
{
    static_assert(is_same<AddLValueReference<string>, string&>::value,
        "Expected add_rvalue_reference_t<string> to be string&");
    static_assert(is_same<AddLValueReference<string*>, string*&>::value,
        "Expected add_rvalue_reference_t<string*> to be string*&");
    static_assert(is_same<AddLValueReference<string&>, string&>::value,
        "Expected add_rvalue_reference_t<string&> to be string&");
    static_assert(is_same<AddLValueReference<string&&>, string&>::value,
        "Expected add_rvalue_reference_t<string&&> to be string&");
    cout << "All static_assert tests of AddLValueReference passed." << endl;

    static_assert(is_same<AddRValueReference<string>, string&&>::value,
        "Expected add_rvalue_reference_t<string> to be string&&");
    static_assert(is_same<AddRValueReference<string*>, string*&&>::value,
        "Expected add_rvalue_reference_t<string*> to be string*&&");
    static_assert(is_same<AddRValueReference<string&>, string&>::value,
        "Expected add_rvalue_reference_t<string&> to be string&");
    static_assert(is_same<AddRValueReference<string&&>, string&&>::value,
        "Expected add_rvalue_reference_t<string&&> to be string&&");
    cout << "All static_assert tests of AddRValueReference passed." << endl;

}

这里和标准库一样,对void类型做了特化;并且还有一点,在用法上,如果左值和右值使用了add_lvalue_reference,仍然是左值,如果左值使用了add_rvalue_reference,也仍是左值引用,如果右值使用了add_rvalue_reference,才是右值引用(具体逻辑可参考引用折叠相关的知识点),上述main函数中的例子也证明了该逻辑。

1.3 移除限制符(包含移除const,volatile——std::remove_volatile<> , std::remove_const<>,std::remove_cv<>)

template<typename T>
struct RemoveConstT
{
    using type = T;
};

template<typename T>
struct RemoveConstT<T const>
{
    using type = T;
};

template<typename T>
using RemoveConst = typename RemoveConstT<T>::type;


template<typename T>
struct RemoveVolatileT
{
    using type = T;
};

template<typename T>
struct RemoveVolatileT<T volatile>
{
    using type = T;
};

template<typename T>
using RemoveVolatile = typename RemoveVolatileT<T>::type;


template<typename T>
struct RemoveCVT : RemoveConstT<typename RemoveVolatileT<T>::type>
{
};
template<typename T>
using RemoveCV = typename RemoveCVT<T>::type;

//template<typename T>
//using RemoveCV =  RemoveVolatile<RemoveConst<T>>;

int main(int argc, char ** argv)
{

    static_assert(is_same<RemoveVolatile<int volatile>, int>::value,
        "Expected RemoveVolatile");
    static_assert(is_same<RemoveConst<int const>, int>::value,
        "Expected RemoveConst");
    static_assert(is_same<RemoveCV<int const volatile>, int>::value,
        "Expected RemoveCV");
}

1.4 退化(std::decay)

数组会退化为指针,函数类型退化成指向函数的指针,并且会删除顶层的const volatile以及引用限制符;

template<typename T>
struct DecayT : RemoveCVT<T>
{

};

template<typename T>
struct DecayT<T[]>
{
    using type = T*;
};

template<typename T,std::size_t N>
struct DecayT<T[N]>
{
    using type = T*;
};

template <typename R,typename... Args>
struct DecayT<R(Args...)>
{
    using type = R(*)(Args...);
};

template <typename R,typename... Args>
struct DecayT<R(Args...,...)>
{
    using type = R(*)(Args...,...);
};

template<typename T>
using Decay = typename DecayT<T>::type;

int main(int argc, char ** argv)
{

    static_assert(is_same<Decay<int volatile>, int>::value,
        "Expected Decay");
    static_assert(is_same<Decay<int const>, int>::value,
        "Expected Decay");
    static_assert(is_same<Decay<int const volatile>, int>::value,
        "Expected Decay");
    static_assert(is_same<Decay<int[10]>, int*>::value,
        "Expected Decay");
    static_assert(is_same<Decay<int(int ,int)>, int(*)(int ,int)>::value,
        "Expected Decay");
}

2 预测型萃取

2.1 判断类型是否相同(std::is_same<>)

template<typename T1,typename T2>
struct isSameT
{
    static constexpr bool value = false;
};
template<typename T>
struct isSameT<T,T>
{
    static constexpr bool value = true;
};
template<typename T1,typename T2>
constexpr bool isSame = isSameT<T1,T2>::value;


int main(int argc, char ** argv)
{

    static_assert(isSame<int, int>,
        "Expected isSame");
}

2.2 true_type和false_type

template<bool val>
struct BoolConstant
{
    using type = BoolConstant<val>;//注释一样可以实现功能,这句什么作用:
    //可以用于别名,using isSame = typename IsSameT<T>::Type;
    static constexpr bool value = val;
};

using TrueType = BoolConstant<true>;
using FalseType = BoolConstant<false>;

template<typename T1,typename T2>
struct isSameT:FalseType{};

template<typename T>
struct isSameT<T,T>:TrueType{};

template<typename T1,typename T2>
constexpr bool isSame = isSameT<T1,T2>::value;

上述的is_same还可以通过BoolConstant的方式进行实现了TrueType和FalseType,其主要作用就是用于类型预测时,可以不用再直接定义value是true还是false,可以在偏特化场景下,直接继承rueType和FalseType,实现2.1的功能;

2.3 获取两个不同类型相加函数的返回值类型

template<typename T1, typename T2>
struct PlusResultT {
using Type = decltype(std::declval<T1>() + std::declval<T2>());
};
template<typename T1, typename T2>
using PlusResult = typename PlusResultT<T1, T2>::Type;
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值