为了方便查看结果,后面测试全部返回true。
type_traits库提供一组特征类,可以在编译器确定类型或者说是元数据是否拥有某特征,是否支持原生数组,是否是证书,是否重载某运算符,检查是否同一类型,还有添加或移除const,volatitle等
is_integral : 检查T是否为bool,char,int等整形
is_floating_point : 检查T是否为浮点型
is_void : 检查T是否为void类新型
std:: cout << (std::is_integral<const char>::value) << "\n";
std::cout << (!std::is_integral<void*>::value) << "\n";
std::cout << (std::is_array<int[]>::value) << "\n";
std::cout << (std::is_class<std::string>::value) << "\n";
std::cout << (std::is_class<class Demo>::value) << "\n";
std::cout << (std::is_pointer<int*>::value) << "\n";
std::cout << (std::is_function<void(int)>::value) << "\n";
std::cout << (std::is_lvalue_reference<float&>::value) << "\n";
std::cout << (std::is_rvalue_reference<float&&>::value) << "\n";
class Demo
{
int x;
double y;
void z() {};
std::function<void()> f = std::bind(&Demo::z,this);
};
std::cout << (std::is_member_object_pointer<int Demo::*>::value) << "\n";
std::cout << (std::is_member_object_pointer < std::function<void()> Demo::*>::value) << "\n";
std::cout << (std::is_member_function_pointer<void(Demo::*)()>::value) << "\n";
复合类型检查
std::cout << (std::rank<int[2][3]>::value == 2) << "\n";
std::cout << (std::extent<int[2][3], 1>::value == 3) << "\n";
添加和删除各种修饰符,输入一个类型,输出一个新的类型type,可以随意处理c++类型
typedef std::add_const<int>::type md1;
std::cout << (std::is_same<md1, int const>::value) << "\n";
typedef std::add_volatile<int const>::type md2;
std::cout << (std::is_same<md2, int const volatile>::value) << "\n";
typedef std::add_pointer<int>::type md3;
std::cout << (std::is_same<md3, int *>::value) << "\n";
typedef std::add_lvalue_reference<md3>::type md4;
std::cout << (std::is_same<md4, int *&>::value) << "\n";
typedef std::add_rvalue_reference<void>::type md5;
std::cout << (std::is_void<md5>::value) << "\n";
typedef int const **& rmd1;
typedef std::remove_pointer<rmd1>::type rmd2;
std::cout << (std::is_same<rmd1, rmd2>::value) << "\n"; //该变量是双指针引用,需要先移除引用
typedef std::remove_reference<rmd2>::type rmd3;
std::cout << (std::is_same<rmd3, int const **>::value) << "\n";
typedef std::remove_pointer<std::remove_pointer<rmd3>::type>::type rmd4;
std::cout << (std::is_same<rmd4, int const>::value) << "\n";
typedef std::remove_const<rmd4>::type rmd5;
std::cout << (std::is_same<rmd5, int>::value) << "\n";
typedef std::remove_extent<int[1][2][5][7]>::type re1;
std::cout << (std::is_same<re1, int[2][5][7]>::value) << "\n";
typedef std::remove_all_extents<int[1][5][7]>::type re2;
std::cout << (std::is_same<re2, int>::value) << "\n";
typedef std::common_type<int, char>::type ct1;
std::cout << (std::is_same<ct1, int>::value) << "\n";
typedef std::common_type<int, double>::type ct2;
std::cout << (std::is_same<ct2, double>::value) << "\n";
//typedef std::common_type::type ct3;//编译错误
很多值元函数都是用了元函数转发技术,把元参数转发给integral_constant计算,该类也是很多类的的public基类。
源码:
template<typename T, T val>
struct integral_constant
{
static const T value = val;
typedef T value_type;
typedef integral_constant<T, val> type;
constexpr operator value_type() const _NOEXCEPT
{
return (value);
}
constexpr value_type operator()() const _NOEXCEPT
{
return(value);
}
};
type_traits库中提供了以下两个针对bool元数据特化的无参元函数true_type和false_type,看起来像SGI stl中实现的__true_type和__false_type:
typedef integral_constant<bool, true> true_type;
typedef integral_constant<bool, false> false_type;
is_integral使用了模板特化技术,对非整数的类型元函数的::value返回false,否则特化地返回true,代码如下:
template<typename T> struct is_integral :public false_type {};
template<> struct is_integral<bool> :public true_type {};
template<> struct is_integral<char> :public true_type {};
template<> struct is_integral<unsigned int> :public true_type {};
template<> struct is_integral<signed int> :public true_type {};
template<typename T, typename U> struct myis_same :public false_type {};
template<typename T> struct myis_same<T,T> :public true_type {};
template<typename T> struct is_void : is_same<void, typename std::remove_cv<T>::type> {};
template<typename T >
struct is_floating_point : integral_constant<bool, (is_same<float, typename std::remove_cv<T>::type>::value
|| is_same<double, typename std::remove_cv<T>::type>::value
|| is_same<long double, typename std::remove_cv<T>::type>::value)>{};
template<typename T> struct is_array :public false_type {};
template<typename T> struct is_array<T[]> :public true_type {};
template<typename T,std::size_t N> struct is_array<T[N]> :public true_type {};
template<typename T> struct is_pointer_helper :public false_type {};
template<typename T> struct is_pointer_helper<T*> :public true_type {};
template<typename T> struct is_pointer :public is_pointer_helper<typename std::remove_cv<T>::type> {};
template<typename T> struct is_member_pointer_helper :public false_type {};
template<typename T,class U> struct is_member_pointer_helper<T (U::*)> :public true_type {};
template<typename T> struct is_member_pointer :public is_member_pointer_helper<typename std::remove_cv<T>::type> {};
测试:
std::cout << (expr::is_member_pointer<int demo1::*>::value ? "is member pointer\n" : "is not member pointer\n");
std::cout << (expr::is_member_pointer<int(demo2::*)>::value ? "is member pointer\n" : "is not member pointer\n");
输出:
is member pointer
is member pointer
并不是判断类T中是否真的有返回值为int的函数,或者是否有int型变量,而是只是判断T这个写法是否是成员函数指针、指向成员变量指针类型。
template<typename T> char check(int T::*) {}; //T是class,struct,返回一个大小的char
struct two { char c[2]; };
template<typename T> two check(...) {}; //T是非class ,struct返回两个大小的char
//is_union,排除union体
template<typename T> struct is_class :public integral_constant<bool, sizeof(check<T>(0)) == 1 && !std::is_union<T>::value>{};
template<typename Based,typename Derived,bool = (is_class<Based>::value && is_class<Derived>::value)>
class is_base_of
{
template<typename T>
static char helper(Derived, T) {};
static int helper(Based, int) {};
struct Conv
{
operator Derived();
operator Based() const;
};
public:
static const bool value = sizeof(helper(Conv(),0)) == 1;
};
template<typename Based,typename Derived>
class is_base_of<Based,Derived,false>
{
public:
static const bool value = is_same<Based, Derived>::value;
};