c++ traits

当函数,类或者一些封装的通用算法中的某些部分会因为数据类型不同而导致处理或逻辑不同(而我们又不希望因为数据类型的差异而修改算法本身的封装时),traits会是一种很好的解决方案。

本以为能很简单的描述它,谁知道还是用了如此长的句子才说明清楚,相当的惭愧。大家只要有个大概的概念就ok了,甚至即使完全没概念也没关系,下面会通过实际代码来说明。

#include   
template<typename T>  
constexpr bool is_pod(T) {  
    return std::is_pod::value;  
}  

这里就定义了一个名为is_pod的函数模板。该函数模板只是type_traits中模板类is_pod的简单包装。通过该函数,我们可以判断一个类型的数据是否为POD类型的:

int main(){  
    int a;  
    std::cout << is_pod(a) << std::endl;  
}  

值得注意的是,Type Traits是用于元编程中的元素,而且我们的函数表达式使用了constexpr进行修饰,那么这就意味着程序员可以在编译时期就获得is_pod返回的值。在本例中,我们获得的值为true(1),那么上面的main函数在运行时的代码将与:

int main(){  
    std::cout << 1 << std::endl;  
}  

等价
c++ traits_第1张图片

这里我们只摘取了一部分。在最初的设计中,C++语言设计者为的Type Traits进行了简单的分类。不过在后来的语言标准中,Type Traits也几经修正演化,也不是由一个文档能够观察全貌的。所幸的是上面的链接应该提供了最新的Type Traits的内容。
除去判断类型的特性,中我们也可以找到is_same这样的比较两个类型是否相等的类模板,以及enable_if这样的根据bool值选择类型的类模板,读者可以从上面链接中寻找其使用方式。

true_type 和 false_type就是包含一个静态类成员value的类模板,其静态成员一个为true,一个为false,仅此而已。这样一来,通过特化,如果我们使用const类型作为模板is_const类型参数,则可以获得其常量静态成员value的值为true(1)。这是因为模板在实例化的时候选择了“版本2”。反过来,如果模板实例化到“版本1”,则value常量静态成员为false(0)。如下例所示:

#include   
#include   

int main(){  
    int a;  
    const int b = 3;  
    std::cout << std::is_const<decltype(a)>::value << std::endl;    // 1  
    std::cout << std::is_const<decltype(b)>::value << std::endl;    // 0  
} 

此外,还有一点值得指出,并非所有的Type Traits都能够使用上面的元编程的手段来实现。C++语言设计者在实践中进行了一些考量,让部分的Type Traits实现为了intrinsic,简单地说,就是要编译器辅助来计算出其值。我们可以看看g++4.8.1中POD的定义:

/// is_pod  
// Could use is_standard_layout && is_trivial instead of the builtin.  
template  
  struct is_pod  
  : public integral_constant<bool, __is_pod(_Tp)>  
  { };  

这里的__is_pod就是编译器内部的intrinsic。事实上,在C++11中,编译器必须辅助实现很多Type Traits的模板类,C++11标准中这些Type Traits模板类如下所示:

template <class T> struct is_class;  
template <class T> struct is_union;  
template <class T> struct is_enum;  
template <class T> struct is_polymorphic;  
template <class T> struct is_empty;  
template <class T> struct has_trivial_constructor;  
template <class T> struct has_trivial_copy;  
template <class T> struct has_trivial_assign;  
template <class T> struct has_trivial_destructor;  
template <class T> struct has_nothrow_constructor;  
template <class T> struct has_nothrow_copy;  
template <class T> struct has_nothrow_assign;  
template <class T> struct is_pod;  
template <class T> struct is_abstract;  

你可能感兴趣的:(C++进阶)