Horizon
meta.hpp
1 #pragma once
2 
3 #include <ciso646> // not
4 #include <cstddef> // size_t
5 #include <limits> // numeric_limits
6 #include <type_traits> // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type
7 #include <utility> // declval
8 
9 #include <nlohmann/json_fwd.hpp>
10 #include <nlohmann/detail/macro_scope.hpp>
11 
12 namespace nlohmann
13 {
22 namespace detail
23 {
25 // helpers //
27 
28 template<typename> struct is_basic_json : std::false_type {};
29 
30 NLOHMANN_BASIC_JSON_TPL_DECLARATION
31 struct is_basic_json<NLOHMANN_BASIC_JSON_TPL> : std::true_type {};
32 
33 // alias templates to reduce boilerplate
34 template<bool B, typename T = void>
35 using enable_if_t = typename std::enable_if<B, T>::type;
36 
37 template<typename T>
38 using uncvref_t = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
39 
40 // implementation of C++14 index_sequence and affiliates
41 // source: https://stackoverflow.com/a/32223343
42 template<std::size_t... Ints>
44 {
45  using type = index_sequence;
46  using value_type = std::size_t;
47  static constexpr std::size_t size() noexcept
48  {
49  return sizeof...(Ints);
50  }
51 };
52 
53 template<class Sequence1, class Sequence2>
55 
56 template<std::size_t... I1, std::size_t... I2>
58  : index_sequence < I1..., (sizeof...(I1) + I2)... > {};
59 
60 template<std::size_t N>
62  : merge_and_renumber < typename make_index_sequence < N / 2 >::type,
63  typename make_index_sequence < N - N / 2 >::type > {};
64 
65 template<> struct make_index_sequence<0> : index_sequence<> {};
66 template<> struct make_index_sequence<1> : index_sequence<0> {};
67 
68 template<typename... Ts>
69 using index_sequence_for = make_index_sequence<sizeof...(Ts)>;
70 
71 /*
72 Implementation of two C++17 constructs: conjunction, negation. This is needed
73 to avoid evaluating all the traits in a condition
74 
75 For example: not std::is_same<void, T>::value and has_value_type<T>::value
76 will not compile when T = void (on MSVC at least). Whereas
77 conjunction<negation<std::is_same<void, T>>, has_value_type<T>>::value will
78 stop evaluating if negation<...>::value == false
79 
80 Please note that those constructs must be used with caution, since symbols can
81 become very long quickly (which can slow down compilation and cause MSVC
82 internal compiler errors). Only use it when you have to (see example ahead).
83 */
84 template<class...> struct conjunction : std::true_type {};
85 template<class B1> struct conjunction<B1> : B1 {};
86 template<class B1, class... Bn>
87 struct conjunction<B1, Bn...> : std::conditional<bool(B1::value), conjunction<Bn...>, B1>::type {};
88 
89 template<class B> struct negation : std::integral_constant<bool, not B::value> {};
90 
91 // dispatch utility (taken from ranges-v3)
92 template<unsigned N> struct priority_tag : priority_tag < N - 1 > {};
93 template<> struct priority_tag<0> {};
94 
96 // has_/is_ functions //
98 
99 // source: https://stackoverflow.com/a/37193089/4116453
100 
101 template <typename T, typename = void>
102 struct is_complete_type : std::false_type {};
103 
104 template <typename T>
105 struct is_complete_type<T, decltype(void(sizeof(T)))> : std::true_type {};
106 
107 NLOHMANN_JSON_HAS_HELPER(mapped_type);
108 NLOHMANN_JSON_HAS_HELPER(key_type);
109 NLOHMANN_JSON_HAS_HELPER(value_type);
110 NLOHMANN_JSON_HAS_HELPER(iterator);
111 
112 template<bool B, class RealType, class CompatibleObjectType>
113 struct is_compatible_object_type_impl : std::false_type {};
114 
115 template<class RealType, class CompatibleObjectType>
116 struct is_compatible_object_type_impl<true, RealType, CompatibleObjectType>
117 {
118  static constexpr auto value =
119  std::is_constructible<typename RealType::key_type, typename CompatibleObjectType::key_type>::value and
120  std::is_constructible<typename RealType::mapped_type, typename CompatibleObjectType::mapped_type>::value;
121 };
122 
123 template<class BasicJsonType, class CompatibleObjectType>
125 {
126  static auto constexpr value = is_compatible_object_type_impl <
128  has_mapped_type<CompatibleObjectType>,
129  has_key_type<CompatibleObjectType>>::value,
130  typename BasicJsonType::object_t, CompatibleObjectType >::value;
131 };
132 
133 template<typename BasicJsonType, typename T>
135 {
136  static auto constexpr value = std::is_same<T, typename BasicJsonType::iterator>::value or
137  std::is_same<T, typename BasicJsonType::const_iterator>::value or
138  std::is_same<T, typename BasicJsonType::reverse_iterator>::value or
139  std::is_same<T, typename BasicJsonType::const_reverse_iterator>::value;
140 };
141 
142 template<class BasicJsonType, class CompatibleArrayType>
144 {
145  static auto constexpr value =
148  BasicJsonType, CompatibleArrayType>>,
149  negation<std::is_constructible<typename BasicJsonType::string_t,
150  CompatibleArrayType>>,
152  has_value_type<CompatibleArrayType>,
153  has_iterator<CompatibleArrayType>>::value;
154 };
155 
156 template<bool, typename, typename>
157 struct is_compatible_integer_type_impl : std::false_type {};
158 
159 template<typename RealIntegerType, typename CompatibleNumberIntegerType>
160 struct is_compatible_integer_type_impl<true, RealIntegerType, CompatibleNumberIntegerType>
161 {
162  // is there an assert somewhere on overflows?
163  using RealLimits = std::numeric_limits<RealIntegerType>;
164  using CompatibleLimits = std::numeric_limits<CompatibleNumberIntegerType>;
165 
166  static constexpr auto value =
167  std::is_constructible<RealIntegerType, CompatibleNumberIntegerType>::value and
168  CompatibleLimits::is_integer and
169  RealLimits::is_signed == CompatibleLimits::is_signed;
170 };
171 
172 template<typename RealIntegerType, typename CompatibleNumberIntegerType>
174 {
175  static constexpr auto value =
177  std::is_integral<CompatibleNumberIntegerType>::value and
178  not std::is_same<bool, CompatibleNumberIntegerType>::value,
179  RealIntegerType, CompatibleNumberIntegerType > ::value;
180 };
181 
182 // trait checking if JSONSerializer<T>::from_json(json const&, udt&) exists
183 template<typename BasicJsonType, typename T>
185 {
186  private:
187  // also check the return type of from_json
188  template<typename U, typename = enable_if_t<std::is_same<void, decltype(uncvref_t<U>::from_json(
189  std::declval<BasicJsonType>(), std::declval<T&>()))>::value>>
190  static int detect(U&&);
191  static void detect(...);
192 
193  public:
194  static constexpr bool value = std::is_integral<decltype(
195  detect(std::declval<typename BasicJsonType::template json_serializer<T, void>>()))>::value;
196 };
197 
198 // This trait checks if JSONSerializer<T>::from_json(json const&) exists
199 // this overload is used for non-default-constructible user-defined-types
200 template<typename BasicJsonType, typename T>
202 {
203  private:
204  template <
205  typename U,
206  typename = enable_if_t<std::is_same<
207  T, decltype(uncvref_t<U>::from_json(std::declval<BasicJsonType>()))>::value >>
208  static int detect(U&&);
209  static void detect(...);
210 
211  public:
212  static constexpr bool value = std::is_integral<decltype(detect(
213  std::declval<typename BasicJsonType::template json_serializer<T, void>>()))>::value;
214 };
215 
216 // This trait checks if BasicJsonType::json_serializer<T>::to_json exists
217 template<typename BasicJsonType, typename T>
219 {
220  private:
221  template<typename U, typename = decltype(uncvref_t<U>::to_json(
222  std::declval<BasicJsonType&>(), std::declval<T>()))>
223  static int detect(U&&);
224  static void detect(...);
225 
226  public:
227  static constexpr bool value = std::is_integral<decltype(detect(
228  std::declval<typename BasicJsonType::template json_serializer<T, void>>()))>::value;
229 };
230 
231 template <typename BasicJsonType, typename CompatibleCompleteType>
233 {
234  static constexpr bool value =
235  not std::is_base_of<std::istream, CompatibleCompleteType>::value and
236  not std::is_same<BasicJsonType, CompatibleCompleteType>::value and
239 };
240 
241 template <typename BasicJsonType, typename CompatibleType>
243  : conjunction<is_complete_type<CompatibleType>,
244  is_compatible_complete_type<BasicJsonType, CompatibleType>>
245 {
246 };
247 
248 // taken from ranges-v3
249 template<typename T>
251 {
252  static constexpr T value{};
253 };
254 
255 template<typename T>
256 constexpr T static_const<T>::value;
257 }
258 }
nlohmann::detail::has_from_json
Definition: meta.hpp:184
nlohmann::detail::negation
Definition: meta.hpp:89
nlohmann::detail::conjunction
Definition: meta.hpp:84
nlohmann::detail::is_complete_type
Definition: meta.hpp:102
nlohmann::detail::priority_tag
Definition: meta.hpp:92
nlohmann::detail::is_basic_json_nested_type
Definition: meta.hpp:134
nlohmann
namespace for Niels Lohmann
Definition: adl_serializer.hpp:8
nlohmann::detail::has_non_default_from_json
Definition: meta.hpp:201
nlohmann::detail::merge_and_renumber
Definition: meta.hpp:54
nlohmann::detail::is_compatible_integer_type_impl
Definition: meta.hpp:157
nlohmann::detail::index_sequence
Definition: meta.hpp:43
nlohmann::detail::is_compatible_type
Definition: meta.hpp:242
nlohmann::detail::is_compatible_array_type
Definition: meta.hpp:143
nlohmann::detail::is_compatible_complete_type
Definition: meta.hpp:232
nlohmann::detail::is_basic_json
Definition: meta.hpp:28
nlohmann::detail::conjunction< B1 >
Definition: meta.hpp:85
nlohmann::detail::has_to_json
Definition: meta.hpp:218
nlohmann::detail::is_compatible_object_type
Definition: meta.hpp:124
nlohmann::detail::make_index_sequence
Definition: meta.hpp:61
nlohmann::detail::is_compatible_object_type_impl
Definition: meta.hpp:113
nlohmann::detail::is_compatible_integer_type
Definition: meta.hpp:173
nlohmann::detail::static_const
Definition: meta.hpp:250