type traits
C++ type traits 学习
从integral_constant引入
integral_constant是一个模板类,用于表示一个常量值,它的定义如下:
/// integral_constant
template<typename _Tp, _Tp __v>
struct integral_constant
{
static constexpr _Tp value = __v;
typedef _Tp value_type;
typedef integral_constant<_Tp, __v> type;
// 类型转换运算符
constexpr operator value_type() const { return value; }
#if __cplusplus > 201103L
#define __cpp_lib_integral_constant_callable 201304
// 函数对象
constexpr value_type operator()() const { return value; }
#endif
};
template<typename _Tp, _Tp __v>
constexpr _Tp integral_constant<_Tp, __v>::value;
/// The type used as a compile-time boolean with true value.
typedef integral_constant<bool, true> true_type;
/// The type used as a compile-time boolean with false value.
typedef integral_constant<bool, false> false_type;
这样想要在结构体或类中定义一个整型常量,则可以使该结构体或类继承自 std::integral_constant<type, val>,则该结构体内部就有了一个static const type的value,访问该value即可。
类型判断
以判断是否为整型为例,可以使用std::is_integral<T>,它的部分定义如下:
/// is_integral
template<typename _Tp>
struct is_integral
: public __is_integral_helper<typename remove_cv<_Tp>::type>::type
{ };
template<typename>
struct __is_integral_helper
: public false_type { };
template<>
struct __is_integral_helper<bool>
: public true_type { };
template<>
struct __is_integral_helper<char>
: public true_type { };
template<>
struct __is_integral_helper<signed char>
: public true_type { };
template<>
struct __is_integral_helper<unsigned char>
: public true_type { };
template<>
struct __is_integral_helper<short>
: public true_type { };
template<>
struct __is_integral_helper<unsigned short>
: public true_type { };
template<>
struct __is_integral_helper<int>
: public true_type { };
template<>
struct __is_integral_helper<unsigned int>
: public true_type { };
这里定义了一个模板类__is_integral_helper<T>,它继承自std::false_type,然后对于不同的整型进行了特化,继承自std::true_type。
这样可以直接使用std::is_integral<T>::value来判断T是否为整型,在编译期间就可以得到结果。
类型关系
判断是否为同一类型
template<typename, typename>
struct is_same
: public false_type { };
template<typename _Tp>
struct is_same<_Tp, _Tp>
: public true_type { };
判断是否为基类
template<typename _Base, typename _Derived>
struct is_base_of
: public __is_base_of<_Base, _Derived> { };
头文件中没有找到__is_base_of的定义。
判断能否类型转换
/// is_convertible
template<typename _From, typename _To>
struct is_convertible
: public __is_convertible_helper<_From, _To>::type
{ };
条件选择
在编译期根据一个判断式选择两个类型中的一个
/// Define a member typedef @c type to one of two argument types.
template<bool _Cond, typename _Iftrue, typename _Iffalse>
struct conditional
{ typedef _Iftrue type; };
// Partial specialization for false.
template<typename _Iftrue, typename _Iffalse>
struct conditional<false, _Iftrue, _Iffalse>
{ typedef _Iffalse type; };
条件禁用
在编译期根据一个判断式禁用一个模板
/// Alias template for enable_if
template<bool _Cond, typename _Tp = void>
using enable_if_t = typename enable_if<_Cond, _Tp>::type;
/// Define a member typedef @c type only if a boolean constant is true.
template<bool, typename _Tp = void>
struct enable_if
{ };
// Partial specialization for true.
template<typename _Tp>
struct enable_if<true, _Tp>
{ typedef _Tp type; };
可以用于特定类型的模板的禁用,以及函数的重载。
#include<iostream>
#define APP_VERSION 20181010L
unsigned int GetAppVersion0() { return APP_VERSION; }
struct GetAppVersion : public std::integral_constant<unsigned int, APP_VERSION> {
GetAppVersion(){
std::cout<<"in constructor"<<std::endl;
}
};
template <typename T>
std::enable_if_t<std::is_integral<T>::value, T> f(T t)
{
return t;
}
template <typename T>
typename std::enable_if<!std::is_integral<T>::value>::type f(T t)
{
std::cout << t << std::endl;
}
int main()
{
GetAppVersion app;
// 函数
std::cout << GetAppVersion0() << std::endl;
// 类内部的常量
std::cout << GetAppVersion::value << std::endl;
// 临时对象
std::cout << GetAppVersion() <<std::endl;
// 函数对象
std::cout << app() <<std::endl;
// 类型转换
std::cout << app <<std::endl;
std::integral_constant<int,100> ic;
std::cout<<ic.value<<std::endl;
std::cout<<std::integral_constant<int,100>::value<<std::endl;
std::cout<<ic()<<std::endl;
std::cout<<ic<<std::endl;
std::cout << std::is_integral<int>::value << std::endl;
std::cout << std::is_same<int, int>::value << std::endl;
std::cout << std::is_convertible<int, int>::value << std::endl;
std::conditional<true, int, double>::type a = 1;
std::cout << f(1) << std::endl;
f(1.0);
// std::cout << f(1.0) << std::endl;
// f(1);
return 0;
}