blob: 1bfc1ac814a23ceb186a9fcf6fa5924281d92783 [file] [log] [blame]
[email protected]93540582011-05-16 22:35:141// Copyright (c) 2011 The Chromium Authors. All rights reserved.
[email protected]951269b2010-06-15 19:39:242// 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_
[email protected]951269b2010-06-15 19:39:247
danakja26bdfc2016-04-13 22:08:038#include <stddef.h>
jbroman6bcfec422016-05-26 00:28:469#include <iosfwd>
tzik403cb6c2016-03-10 07:17:2510#include <type_traits>
danakja26bdfc2016-04-13 22:08:0311#include <utility>
[email protected]b38d3572011-02-15 01:27:3812
[email protected]792cdcf2010-12-15 09:55:3513#include "build/build_config.h"
14
alshabalinf06b07df2016-05-27 08:01:3115// 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
[email protected]951269b2010-06-15 19:39:2426namespace base {
27
tzik403cb6c2016-03-10 07:17:2528template <class T> struct is_non_const_reference : std::false_type {};
29template <class T> struct is_non_const_reference<T&> : std::true_type {};
30template <class T> struct is_non_const_reference<const T&> : std::false_type {};
[email protected]b38d3572011-02-15 01:27:3831
danakja26bdfc2016-04-13 22:08:0332// is_assignable
33
34namespace internal {
35
36template <typename First, typename Second>
37struct SelectSecond {
38 using type = Second;
39};
40
41struct 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.
47template <class Lvalue, class Rvalue>
48typename internal::SelectSecond<
49 decltype((std::declval<Lvalue>() = std::declval<Rvalue>())),
50 std::true_type>::type
51IsAssignableTest(Lvalue&&, Rvalue&&);
52
53// False case: Otherwise the return value is a false_type.
54template <class Rvalue>
55std::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.
59template <class Lvalue,
60 class Rvalue,
61 bool = std::is_void<Lvalue>::value || std::is_void<Rvalue>::value>
62struct 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.
69template <class Lvalue, class Rvalue>
70struct IsAssignableImpl<Lvalue, Rvalue, true> : public std::false_type {};
71
jbroman6bcfec422016-05-26 00:28:4672// Uses expression SFINAE to detect whether using operator<< would work.
73template <typename T, typename = void>
74struct SupportsOstreamOperator : std::false_type {};
75template <typename T>
76struct SupportsOstreamOperator<T,
77 decltype(void(std::declval<std::ostream&>()
78 << std::declval<T>()))>
79 : std::true_type {};
80
danakja26bdfc2016-04-13 22:08:0381} // namespace internal
82
83// TODO(crbug.com/554293): Remove this when all platforms have this in the std
84// namespace.
85template <class Lvalue, class Rvalue>
86struct 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.
91template <class T>
92struct 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.
100template <class T>
101struct 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
jbroman6bcfec422016-05-26 00:28:46106// underlying_type produces the integer type backing an enum type.
jbroman6bcfec422016-05-26 00:28:46107// TODO(crbug.com/554293): Remove this when all platforms have this in the std
108// namespace.
alshabalinf06b07df2016-05-27 08:01:31109#if defined(CR_USE_FALLBACKS_FOR_OLD_GLIBCXX)
jbroman6bcfec422016-05-26 00:28:46110template <typename T>
111struct underlying_type {
112 using type = __underlying_type(T);
113};
114#else
115template <typename T>
116using underlying_type = std::underlying_type<T>;
117#endif
118
alshabalinf06b07df2016-05-27 08:01:31119// 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)
122template <class T>
123using is_trivially_destructible = std::has_trivial_destructor<T>;
124#else
125template <class T>
126using is_trivially_destructible = std::is_trivially_destructible<T>;
127#endif
128
[email protected]951269b2010-06-15 19:39:24129} // namespace base
130
alshabalinf06b07df2016-05-27 08:01:31131#undef CR_USE_FALLBACKS_FOR_OLD_GLIBCXX
132
[email protected]81e8ebf2010-09-16 07:59:27133#endif // BASE_TEMPLATE_UTIL_H_