• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #pragma once
2 
3 #include <cstddef> // size_t
4 #include <type_traits> // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type
5 #include <utility> // index_sequence, make_index_sequence, index_sequence_for
6 
7 #include <nlohmann/detail/macro_scope.hpp>
8 
9 namespace nlohmann
10 {
11 namespace detail
12 {
13 
14 template<typename T>
15 using uncvref_t = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
16 
17 #ifdef JSON_HAS_CPP_14
18 
19 // the following utilities are natively available in C++14
20 using std::enable_if_t;
21 using std::index_sequence;
22 using std::make_index_sequence;
23 using std::index_sequence_for;
24 
25 #else
26 
27 // alias templates to reduce boilerplate
28 template<bool B, typename T = void>
29 using enable_if_t = typename std::enable_if<B, T>::type;
30 
31 // The following code is taken from https://github.com/abseil/abseil-cpp/blob/10cb35e459f5ecca5b2ff107635da0bfa41011b4/absl/utility/utility.h
32 // which is part of Google Abseil (https://github.com/abseil/abseil-cpp), licensed under the Apache License 2.0.
33 
34 //// START OF CODE FROM GOOGLE ABSEIL
35 
36 // integer_sequence
37 //
38 // Class template representing a compile-time integer sequence. An instantiation
39 // of `integer_sequence<T, Ints...>` has a sequence of integers encoded in its
40 // type through its template arguments (which is a common need when
41 // working with C++11 variadic templates). `absl::integer_sequence` is designed
42 // to be a drop-in replacement for C++14's `std::integer_sequence`.
43 //
44 // Example:
45 //
46 //   template< class T, T... Ints >
47 //   void user_function(integer_sequence<T, Ints...>);
48 //
49 //   int main()
50 //   {
51 //     // user_function's `T` will be deduced to `int` and `Ints...`
52 //     // will be deduced to `0, 1, 2, 3, 4`.
53 //     user_function(make_integer_sequence<int, 5>());
54 //   }
55 template <typename T, T... Ints>
56 struct integer_sequence
57 {
58     using value_type = T;
sizenlohmann::detail::integer_sequence59     static constexpr std::size_t size() noexcept
60     {
61         return sizeof...(Ints);
62     }
63 };
64 
65 // index_sequence
66 //
67 // A helper template for an `integer_sequence` of `size_t`,
68 // `absl::index_sequence` is designed to be a drop-in replacement for C++14's
69 // `std::index_sequence`.
70 template <size_t... Ints>
71 using index_sequence = integer_sequence<size_t, Ints...>;
72 
73 namespace utility_internal
74 {
75 
76 template <typename Seq, size_t SeqSize, size_t Rem>
77 struct Extend;
78 
79 // Note that SeqSize == sizeof...(Ints). It's passed explicitly for efficiency.
80 template <typename T, T... Ints, size_t SeqSize>
81 struct Extend<integer_sequence<T, Ints...>, SeqSize, 0>
82 {
83     using type = integer_sequence < T, Ints..., (Ints + SeqSize)... >;
84 };
85 
86 template <typename T, T... Ints, size_t SeqSize>
87 struct Extend<integer_sequence<T, Ints...>, SeqSize, 1>
88 {
89     using type = integer_sequence < T, Ints..., (Ints + SeqSize)..., 2 * SeqSize >;
90 };
91 
92 // Recursion helper for 'make_integer_sequence<T, N>'.
93 // 'Gen<T, N>::type' is an alias for 'integer_sequence<T, 0, 1, ... N-1>'.
94 template <typename T, size_t N>
95 struct Gen
96 {
97     using type =
98         typename Extend < typename Gen < T, N / 2 >::type, N / 2, N % 2 >::type;
99 };
100 
101 template <typename T>
102 struct Gen<T, 0>
103 {
104     using type = integer_sequence<T>;
105 };
106 
107 }  // namespace utility_internal
108 
109 // Compile-time sequences of integers
110 
111 // make_integer_sequence
112 //
113 // This template alias is equivalent to
114 // `integer_sequence<int, 0, 1, ..., N-1>`, and is designed to be a drop-in
115 // replacement for C++14's `std::make_integer_sequence`.
116 template <typename T, T N>
117 using make_integer_sequence = typename utility_internal::Gen<T, N>::type;
118 
119 // make_index_sequence
120 //
121 // This template alias is equivalent to `index_sequence<0, 1, ..., N-1>`,
122 // and is designed to be a drop-in replacement for C++14's
123 // `std::make_index_sequence`.
124 template <size_t N>
125 using make_index_sequence = make_integer_sequence<size_t, N>;
126 
127 // index_sequence_for
128 //
129 // Converts a typename pack into an index sequence of the same length, and
130 // is designed to be a drop-in replacement for C++14's
131 // `std::index_sequence_for()`
132 template <typename... Ts>
133 using index_sequence_for = make_index_sequence<sizeof...(Ts)>;
134 
135 //// END OF CODE FROM GOOGLE ABSEIL
136 
137 #endif
138 
139 // dispatch utility (taken from ranges-v3)
140 template<unsigned N> struct priority_tag : priority_tag < N - 1 > {};
141 template<> struct priority_tag<0> {};
142 
143 // taken from ranges-v3
144 template<typename T>
145 struct static_const
146 {
147     static constexpr T value{};
148 };
149 
150 template<typename T>
151 constexpr T static_const<T>::value;
152 
153 }  // namespace detail
154 }  // namespace nlohmann
155