两年前的一道面试题
这段时间一直在看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