• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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