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;