Home | History | Annotate | Download | only in base
      1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #ifndef BASE_TEMPLATE_UTIL_H_
      6 #define BASE_TEMPLATE_UTIL_H_
      7 
      8 #include <cstddef>  // For size_t.
      9 
     10 #include "build/build_config.h"
     11 
     12 namespace base {
     13 
     14 // template definitions from tr1
     15 
     16 template<class T, T v>
     17 struct integral_constant {
     18   static const T value = v;
     19   typedef T value_type;
     20   typedef integral_constant<T, v> type;
     21 };
     22 
     23 template <class T, T v> const T integral_constant<T, v>::value;
     24 
     25 typedef integral_constant<bool, true> true_type;
     26 typedef integral_constant<bool, false> false_type;
     27 
     28 template <class T> struct is_pointer : false_type {};
     29 template <class T> struct is_pointer<T*> : true_type {};
     30 
     31 // Member function pointer detection up to four params. Add more as needed
     32 // below. This is built-in to C++ 11, and we can remove this when we switch.
     33 template<typename T>
     34 struct is_member_function_pointer : false_type {};
     35 
     36 template <typename R, typename Z>
     37 struct is_member_function_pointer<R(Z::*)()> : true_type {};
     38 template <typename R, typename Z>
     39 struct is_member_function_pointer<R(Z::*)() const> : true_type {};
     40 
     41 template <typename R, typename Z, typename A>
     42 struct is_member_function_pointer<R(Z::*)(A)> : true_type {};
     43 template <typename R, typename Z, typename A>
     44 struct is_member_function_pointer<R(Z::*)(A) const> : true_type {};
     45 
     46 template <typename R, typename Z, typename A, typename B>
     47 struct is_member_function_pointer<R(Z::*)(A, B)> : true_type {};
     48 template <typename R, typename Z, typename A, typename B>
     49 struct is_member_function_pointer<R(Z::*)(A, B) const> : true_type {};
     50 
     51 template <typename R, typename Z, typename A, typename B, typename C>
     52 struct is_member_function_pointer<R(Z::*)(A, B, C)> : true_type {};
     53 template <typename R, typename Z, typename A, typename B, typename C>
     54 struct is_member_function_pointer<R(Z::*)(A, B, C) const> : true_type {};
     55 
     56 template <typename R, typename Z, typename A, typename B, typename C,
     57           typename D>
     58 struct is_member_function_pointer<R(Z::*)(A, B, C, D)> : true_type {};
     59 template <typename R, typename Z, typename A, typename B, typename C,
     60           typename D>
     61 struct is_member_function_pointer<R(Z::*)(A, B, C, D) const> : true_type {};
     62 
     63 
     64 template <class T, class U> struct is_same : public false_type {};
     65 template <class T> struct is_same<T,T> : true_type {};
     66 
     67 template<class> struct is_array : public false_type {};
     68 template<class T, size_t n> struct is_array<T[n]> : public true_type {};
     69 template<class T> struct is_array<T[]> : public true_type {};
     70 
     71 template <class T> struct is_non_const_reference : false_type {};
     72 template <class T> struct is_non_const_reference<T&> : true_type {};
     73 template <class T> struct is_non_const_reference<const T&> : false_type {};
     74 
     75 template <class T> struct is_const : false_type {};
     76 template <class T> struct is_const<const T> : true_type {};
     77 
     78 template <class T> struct is_void : false_type {};
     79 template <> struct is_void<void> : true_type {};
     80 
     81 namespace internal {
     82 
     83 // Types YesType and NoType are guaranteed such that sizeof(YesType) <
     84 // sizeof(NoType).
     85 typedef char YesType;
     86 
     87 struct NoType {
     88   YesType dummy[2];
     89 };
     90 
     91 // This class is an implementation detail for is_convertible, and you
     92 // don't need to know how it works to use is_convertible. For those
     93 // who care: we declare two different functions, one whose argument is
     94 // of type To and one with a variadic argument list. We give them
     95 // return types of different size, so we can use sizeof to trick the
     96 // compiler into telling us which function it would have chosen if we
     97 // had called it with an argument of type From.  See Alexandrescu's
     98 // _Modern C++ Design_ for more details on this sort of trick.
     99 
    100 struct ConvertHelper {
    101   template <typename To>
    102   static YesType Test(To);
    103 
    104   template <typename To>
    105   static NoType Test(...);
    106 
    107   template <typename From>
    108   static From& Create();
    109 };
    110 
    111 // Used to determine if a type is a struct/union/class. Inspired by Boost's
    112 // is_class type_trait implementation.
    113 struct IsClassHelper {
    114   template <typename C>
    115   static YesType Test(void(C::*)(void));
    116 
    117   template <typename C>
    118   static NoType Test(...);
    119 };
    120 
    121 }  // namespace internal
    122 
    123 // Inherits from true_type if From is convertible to To, false_type otherwise.
    124 //
    125 // Note that if the type is convertible, this will be a true_type REGARDLESS
    126 // of whether or not the conversion would emit a warning.
    127 template <typename From, typename To>
    128 struct is_convertible
    129     : integral_constant<bool,
    130                         sizeof(internal::ConvertHelper::Test<To>(
    131                                    internal::ConvertHelper::Create<From>())) ==
    132                         sizeof(internal::YesType)> {
    133 };
    134 
    135 template <typename T>
    136 struct is_class
    137     : integral_constant<bool,
    138                         sizeof(internal::IsClassHelper::Test<T>(0)) ==
    139                             sizeof(internal::YesType)> {
    140 };
    141 
    142 template<bool B, class T = void>
    143 struct enable_if {};
    144 
    145 template<class T>
    146 struct enable_if<true, T> { typedef T type; };
    147 
    148 }  // namespace base
    149 
    150 #endif  // BASE_TEMPLATE_UTIL_H_
    151