这段时间一直在看sv6的代码,里面用到了很多c++11里面的新特性,各种右值引用、匿名函数、精确传递什么的,看得我头都大了。

不懂只好去查资料呗,于是就看到了type_traits的内容,不禁想到2012年初去百度面实习生的时候考官问我的一道题目。

题目是这样的:

写一个模板类,要求这个模板类只能接受内置类型的参数(即为int、char之类的),如果传递了自定义类型作为模板参数,则要在编译的时候报错。

当时没有想出来,后来在回南京的火车上想出了这样的一种解法:

template <typename T>
class Constraint;

template class Constraint<int> {};
template class Constraint<char> {};

template <typename T, typename C = Constraint<T> >
class FuckingTemplate {
    ......    
};

int main(int argc, char **argv) {
    FuckingTemplate<int> intT;      // compile OK
    FuckingTemplate<char> charT;    // compile OK
    FuckingTemplate<S> ST;          // compile error
    return 0;
}

FuckingTemplate带两个模板参数,第一个要求用户提供,第二个为默认模板参数并以第一个模板参数为参数。然后第二个模板参数Constraint只声明不定义,只特化了int和char两个版本。结果就是,如果传入了自定义类型S作为模板参数,则会因为找不到Constraint<S>的定义而发生编译错误。

这个做法看上去实在是不甚优雅,现在有了type_traits就可以这么做。

#include <iostream>
#include <type_traits>

template <typename T>
class FuckingTemplate {
    static_assert(std::is_integral<T>::value, "parameter must be an integer\n");
    ......
};

int main(int argc, char **argv) {
    FuckingTemplate<int> intT;      // compile OK
    FuckingTemplate<char> charT;    // compile OK
    FuckintTemplate<S> ST;          // compile error
    return 0;
}

一行代码就可以搞定,可惜当年实在是太弱了,没有想到。这里面用到了c++11中的type_trait和static_assert,这些东西原先都是tr1中的内容,现在被吸收到了c++11标准中了,编译的时候指定-std=c++11就可以搞定。

在type_traits中还有其他很多的traits,比如:

*Primary type categories*
is_array                            Is array (class template )
is_class                            Is class (class template )
is_enum                             Is enum (class template )
is_floating_point                   Is floating point (class template )
is_function                         Is function (class template )
is_integral                         Is integral (class template )
is_lvalue_reference                 Is lvalue reference (class template )
is_member_function_pointer          Is member function pointer (class template )
is_member_object_pointer            Is member object pointer (class template )
is_pointer                          Is pointer (class template )
is_rvalue_reference                 Is rvalue reference (class template )
is_union                            Is union (class template )
is_void                             Is void (class template )
*Composite type categories*
is_arithmetic                       Is arithmetic type (class template )
is_compound                         Is compound type (class template )
is_fundamental                      Is fundamental type (class template )
is_member_pointer                   Is member pointer type (class template )
is_object                           Is object type (class template )
is_reference                        Is reference type (class template )
is_scalar                           Is scalar type (class template )
*Type properties*
is_abstract                         Is abstract class (class template )
is_const                            Is const-qualified (class template )
is_empty                            Is empty class (class template )
is_literal_type                     Is literal type (class template )
is_pod                              Is POD type (class template )
is_polymorphic                      Is polymorphic (class template )
is_signed                           Is signed type (class template )
is_standard_layout                  Is standard-layout type (class template )
is_trivial                          Is trivial type (class template )
is_trivially_copyable               Is trivially copyable (class template )
is_unsigned                         Is unsigned type (class template )
is_volatile                         Is volatile-qualified (class template )
*Type features*
has_virtual_destructor              Has virtual destructor (class template )
is_assignable                       Is assignable (class template )
is_constructible                    Is constructible (class template )
is_copy_assignable                  Is copy assignable (class template )
is_copy_constructible               Is copy constructible (class template )
is_destructible                     Is destructible (class template )
is_default_constructible            Is default constructible (class template )
is_move_assignable                  Is move assignable (class template )
is_move_constructible               Is move constructible (class template )
is_trivially_assignable             Is trivially assignable (class template )
is_trivially_constructible          Is trivially constructible (class template )
is_trivially_copy_assignable        Is trivially copy assignable (class template )
is_trivially_copy_constructible     Is trivially copy constructible (class template )
is_trivially_destructible           Is trivially destructible (class template )
is_trivially_default_constructible  Is trivially default constructible (class template )
is_trivially_move_assignable        Is trivially move assignable (class template )
is_trivially_move_constructible     Is trivially move constructible (class template )
is_nothrow_assignable               Is assignable throwing no exceptions (class template )
is_nothrow_constructible            Is constructible throwing no exceptions (class template )
is_nothrow_copy_assignable          Is copy assignable throwing no exceptions (class template )
is_nothrow_copy_constructible       Is copy constructible throwing no exceptions (class template )
is_nothrow_destructible             Is nothrow destructible (class template )
is_nothrow_default_constructible    Is default constructible throwing no exceptions (class template )
is_nothrow_move_assignable          Is move assignable throwing no exception (class template )
is_nothrow_move_constructible       Is move constructible throwing no exceptions (class template )
*Type relationships*
is_base_of                          Is base class of (class template )
is_convertible                      Is convertible (class template )
is_same                             Is same type (class template )
*Property queries*
alignment_of                        Alignment of (class template )
extent                              Array dimension extent (class template )
rank                                Array rank (class template )

关于这些type_traits是怎么实现的,发现一篇文章写得很好,里面的实现实在是非常非常复杂,水平有限就不详细介绍了。




blog comments powered by Disqus

Published

11 March 2014

Tags