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 <stddef.h> 9 #include <iosfwd> 10 #include <type_traits> 11 #include <utility> 12 13 #include "build/build_config.h" 14 15 // This hacks around libstdc++ 4.6 missing stuff in type_traits, while we need 16 // to support it. 17 #define CR_GLIBCXX_4_7_0 20120322 18 #define CR_GLIBCXX_4_5_4 20120702 19 #define CR_GLIBCXX_4_6_4 20121127 20 #if defined(__GLIBCXX__) && \ 21 (__GLIBCXX__ < CR_GLIBCXX_4_7_0 || __GLIBCXX__ == CR_GLIBCXX_4_5_4 || \ 22 __GLIBCXX__ == CR_GLIBCXX_4_6_4) 23 #define CR_USE_FALLBACKS_FOR_OLD_GLIBCXX 24 #endif 25 26 namespace base { 27 28 template <class T> struct is_non_const_reference : std::false_type {}; 29 template <class T> struct is_non_const_reference<T&> : std::true_type {}; 30 template <class T> struct is_non_const_reference<const T&> : std::false_type {}; 31 32 // is_assignable 33 34 namespace internal { 35 36 template <typename First, typename Second> 37 struct SelectSecond { 38 using type = Second; 39 }; 40 41 struct Any { 42 Any(...); 43 }; 44 45 // True case: If |Lvalue| can be assigned to from |Rvalue|, then the return 46 // value is a true_type. 47 template <class Lvalue, class Rvalue> 48 typename internal::SelectSecond< 49 decltype((std::declval<Lvalue>() = std::declval<Rvalue>())), 50 std::true_type>::type 51 IsAssignableTest(Lvalue&&, Rvalue&&); 52 53 // False case: Otherwise the return value is a false_type. 54 template <class Rvalue> 55 std::false_type IsAssignableTest(internal::Any, Rvalue&&); 56 57 // Default case: Neither Lvalue nor Rvalue is void. Uses IsAssignableTest to 58 // determine the type of IsAssignableImpl. 59 template <class Lvalue, 60 class Rvalue, 61 bool = std::is_void<Lvalue>::value || std::is_void<Rvalue>::value> 62 struct IsAssignableImpl 63 : public std::common_type<decltype( 64 internal::IsAssignableTest(std::declval<Lvalue>(), 65 std::declval<Rvalue>()))>::type {}; 66 67 // Void case: Either Lvalue or Rvalue is void. Then the type of IsAssignableTest 68 // is false_type. 69 template <class Lvalue, class Rvalue> 70 struct IsAssignableImpl<Lvalue, Rvalue, true> : public std::false_type {}; 71 72 // Uses expression SFINAE to detect whether using operator<< would work. 73 template <typename T, typename = void> 74 struct SupportsOstreamOperator : std::false_type {}; 75 template <typename T> 76 struct SupportsOstreamOperator<T, 77 decltype(void(std::declval<std::ostream&>() 78 << std::declval<T>()))> 79 : std::true_type {}; 80 81 } // namespace internal 82 83 // TODO(crbug.com/554293): Remove this when all platforms have this in the std 84 // namespace. 85 template <class Lvalue, class Rvalue> 86 struct is_assignable : public internal::IsAssignableImpl<Lvalue, Rvalue> {}; 87 88 // is_copy_assignable is true if a T const& is assignable to a T&. 89 // TODO(crbug.com/554293): Remove this when all platforms have this in the std 90 // namespace. 91 template <class T> 92 struct is_copy_assignable 93 : public is_assignable<typename std::add_lvalue_reference<T>::type, 94 typename std::add_lvalue_reference< 95 typename std::add_const<T>::type>::type> {}; 96 97 // is_move_assignable is true if a T&& is assignable to a T&. 98 // TODO(crbug.com/554293): Remove this when all platforms have this in the std 99 // namespace. 100 template <class T> 101 struct is_move_assignable 102 : public is_assignable<typename std::add_lvalue_reference<T>::type, 103 const typename std::add_rvalue_reference<T>::type> { 104 }; 105 106 // underlying_type produces the integer type backing an enum type. 107 // TODO(crbug.com/554293): Remove this when all platforms have this in the std 108 // namespace. 109 #if defined(CR_USE_FALLBACKS_FOR_OLD_GLIBCXX) 110 template <typename T> 111 struct underlying_type { 112 using type = __underlying_type(T); 113 }; 114 #else 115 template <typename T> 116 using underlying_type = std::underlying_type<T>; 117 #endif 118 119 // TODO(crbug.com/554293): Remove this when all platforms have this in the std 120 // namespace. 121 #if defined(CR_USE_FALLBACKS_FOR_OLD_GLIBCXX) 122 template <class T> 123 using is_trivially_destructible = std::has_trivial_destructor<T>; 124 #else 125 template <class T> 126 using is_trivially_destructible = std::is_trivially_destructible<T>; 127 #endif 128 129 } // namespace base 130 131 #undef CR_USE_FALLBACKS_FOR_OLD_GLIBCXX 132 133 #endif // BASE_TEMPLATE_UTIL_H_ 134