Blame view

3rdparty/boost_1_81_0/boost/json/impl/conversion.hpp 9.39 KB
63e88f80   Hu Chunming   提交三方库
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
  //
  // Copyright (c) 2020 Krystian Stasiowski (sdkrystian@gmail.com)
  // Copyright (c) 2022 Dmitry Arkhipov (grisumbras@yandex.ru)
  //
  // Distributed under the Boost Software License, Version 1.0. (See accompanying
  // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  //
  // Official repository: https://github.com/boostorg/json
  //
  
  #ifndef BOOST_JSON_IMPL_CONVERSION_HPP
  #define BOOST_JSON_IMPL_CONVERSION_HPP
  
  #include <boost/json/fwd.hpp>
  #include <boost/json/value.hpp>
  #include <boost/json/string_view.hpp>
  #include <boost/describe/enumerators.hpp>
  #include <boost/describe/members.hpp>
  #include <boost/describe/bases.hpp>
  #include <boost/mp11/algorithm.hpp>
  #include <boost/mp11/utility.hpp>
  
  #include <iterator>
  #include <utility>
  #ifndef BOOST_NO_CXX17_HDR_VARIANT
  # include <variant>
  #endif // BOOST_NO_CXX17_HDR_VARIANT
  
  BOOST_JSON_NS_BEGIN
  namespace detail {
  
  #ifdef __cpp_lib_nonmember_container_access
  using std::size;
  #endif
  
  template<std::size_t I, class T>
  using tuple_element_t = typename std::tuple_element<I, T>::type;
  
  template<class T>
  using iterator_type = decltype(std::begin(std::declval<T&>()));
  template<class T>
  using iterator_traits = std::iterator_traits< iterator_type<T> >;
  
  template<class T>
  using value_type = typename iterator_traits<T>::value_type;
  template<class T>
  using mapped_type = tuple_element_t< 1, value_type<T> >;
  
  // had to make the metafunction always succeeding in order to make it work
  // with msvc 14.0
  template<class T>
  using key_type_helper = tuple_element_t< 0, value_type<T> >;
  template<class T>
  using key_type = mp11::mp_eval_or<
      void,
      key_type_helper,
      T>;
  
  template<class T>
  using are_begin_and_end_same = std::is_same<
      iterator_type<T>,
      decltype(std::end(std::declval<T&>()))>;
  
  template<class T>
  using begin_iterator_category = typename std::iterator_traits<
      iterator_type<T>>::iterator_category;
  
  template<class T>
  using has_positive_tuple_size = mp11::mp_bool<
      (std::tuple_size<T>::value > 0) >;
  
  template<class T>
  using has_unique_keys = has_positive_tuple_size<decltype(
      std::declval<T&>().emplace(
          std::declval<value_type<T>>()))>;
  
  template<class T>
  struct is_value_type_pair_helper : std::false_type
  { };
  template<class T1, class T2>
  struct is_value_type_pair_helper<std::pair<T1, T2>> : std::true_type
  { };
  template<class T>
  using is_value_type_pair = is_value_type_pair_helper<value_type<T>>;
  
  template<class T>
  using has_size_member_helper
      = std::is_convertible<decltype(std::declval<T&>().size()), std::size_t>;
  template<class T>
  using has_size_member = mp11::mp_valid_and_true<has_size_member_helper, T>;
  template<class T>
  using has_free_size_helper
      = std::is_convertible<
          decltype(size(std::declval<T const&>())),
          std::size_t>;
  template<class T>
  using has_free_size = mp11::mp_valid_and_true<has_free_size_helper, T>;
  template<class T>
  using size_implementation = mp11::mp_cond<
      has_size_member<T>, mp11::mp_int<3>,
      has_free_size<T>,   mp11::mp_int<2>,
      std::is_array<T>,   mp11::mp_int<1>,
      mp11::mp_true,      mp11::mp_int<0>>;
  
  template<class T>
  std::size_t
  try_size(T&& cont, mp11::mp_int<3>)
  {
      return cont.size();
  }
  
  template<class T>
  std::size_t
  try_size(T& cont, mp11::mp_int<2>)
  {
      return size(cont);
  }
  
  template<class T, std::size_t N>
  std::size_t
  try_size(T(&)[N], mp11::mp_int<1>)
  {
      return N;
  }
  
  template<class T>
  std::size_t
  try_size(T&, mp11::mp_int<0>)
  {
      return 0;
  }
  
  using value_from_conversion = mp11::mp_true;
  using value_to_conversion = mp11::mp_false;
  
  struct user_conversion_tag { };
  struct native_conversion_tag { };
  struct value_conversion_tag : native_conversion_tag { };
  struct object_conversion_tag : native_conversion_tag { };
  struct array_conversion_tag : native_conversion_tag { };
  struct string_conversion_tag : native_conversion_tag { };
  struct bool_conversion_tag : native_conversion_tag { };
  struct number_conversion_tag : native_conversion_tag { };
  struct null_like_conversion_tag { };
  struct string_like_conversion_tag { };
  struct map_like_conversion_tag { };
  struct sequence_conversion_tag { };
  struct tuple_conversion_tag { };
  struct described_class_conversion_tag { };
  struct described_enum_conversion_tag { };
  struct no_conversion_tag { };
  
  template<class T>
  using has_user_conversion_from_impl
      = decltype(tag_invoke(
          value_from_tag(), std::declval<value&>(), std::declval<T&&>()));
  template<class T>
  using has_user_conversion_to_impl
      = decltype(tag_invoke(value_to_tag<T>(), std::declval<value const &>()));
  template<class T>
  using has_nonthrowing_user_conversion_to_impl
      = decltype(tag_invoke(
          try_value_to_tag<T>(), std::declval<value const&>() ));
  template<class T, class Dir>
  using has_user_conversion = mp11::mp_if<
      std::is_same<Dir, value_from_conversion>,
      mp11::mp_valid<has_user_conversion_from_impl, T>,
      mp11::mp_or<
          mp11::mp_valid<has_user_conversion_to_impl, T>,
          mp11::mp_valid<has_nonthrowing_user_conversion_to_impl, T>>>;
  
  template< class T >
  using described_non_public_members = describe::describe_members<
      T, describe::mod_private | describe::mod_protected>;
  template< class T >
  using described_bases = describe::describe_bases<
      T, describe::mod_any_access>;
  
  template<class T, class Dir>
  using conversion_implementation = mp11::mp_cond<
      // user conversion (via tag_invoke)
      has_user_conversion<T, Dir>, user_conversion_tag,
      // native conversions (constructors and member functions of value)
      std::is_same<T, value>,      value_conversion_tag,
      std::is_same<T, array>,      array_conversion_tag,
      std::is_same<T, object>,     object_conversion_tag,
      std::is_same<T, string>,     string_conversion_tag,
      std::is_same<T, bool>,       bool_conversion_tag,
      std::is_arithmetic<T>,       number_conversion_tag,
      // generic conversions
      is_null_like<T>,             null_like_conversion_tag,
      is_string_like<T>,           string_like_conversion_tag,
      is_map_like<T>,              map_like_conversion_tag,
      is_sequence_like<T>,         sequence_conversion_tag,
      is_tuple_like<T>,            tuple_conversion_tag,
      is_described_class<T>,       described_class_conversion_tag,
      is_described_enum<T>,        described_enum_conversion_tag,
      // failed to find a suitable implementation
      mp11::mp_true,                   no_conversion_tag>;
  
  template <class T, class Dir>
  using can_convert = mp11::mp_not<
      std::is_same<
          detail::conversion_implementation<T, Dir>,
          detail::no_conversion_tag>>;
  
  template<class T>
  using value_from_implementation
      = conversion_implementation<T, value_from_conversion>;
  
  template<class T>
  using value_to_implementation
      = conversion_implementation<T, value_to_conversion>;
  
  template<class Impl1, class Impl2>
  using conversion_round_trips_helper = mp11::mp_or<
      std::is_same<Impl1, Impl2>,
      std::is_same<user_conversion_tag, Impl1>,
      std::is_same<user_conversion_tag, Impl2>>;
  template<class T, class Dir>
  using conversion_round_trips  = conversion_round_trips_helper<
      conversion_implementation<T, Dir>,
      conversion_implementation<T, mp11::mp_not<Dir>>>;
  
  template< class T1, class T2 >
  struct copy_cref_helper
  {
      using type = remove_cvref<T2>;
  };
  template< class T1, class T2 >
  using copy_cref = typename copy_cref_helper< T1, T2 >::type;
  
  template< class T1, class T2 >
  struct copy_cref_helper<T1 const, T2>
  {
      using type = remove_cvref<T2> const;
  };
  template< class T1, class T2 >
  struct copy_cref_helper<T1&, T2>
  {
      using type = copy_cref<T1, T2>&;
  };
  template< class T1, class T2 >
  struct copy_cref_helper<T1&&, T2>
  {
      using type = copy_cref<T1, T2>&&;
  };
  
  template< class Rng, class Traits >
  using forwarded_value_helper = mp11::mp_if<
      std::is_convertible<
          typename Traits::reference,
          copy_cref<Rng, typename Traits::value_type> >,
      copy_cref<Rng, typename Traits::value_type>,
      typename Traits::value_type >;
  
  template< class Rng >
  using forwarded_value = forwarded_value_helper<
      Rng, iterator_traits< Rng > >;
  
  } // namespace detail
  
  template <class T>
  struct result_for<T, value>
  {
      using type = result< detail::remove_cvref<T> >;
  };
  
  template<class T>
  struct is_string_like
      : std::is_convertible<T, string_view>
  { };
  
  template<class T>
  struct is_sequence_like
      : mp11::mp_all<
          mp11::mp_valid_and_true<detail::are_begin_and_end_same, T>,
          mp11::mp_valid<detail::begin_iterator_category, T>>
  { };
  
  template<class T>
  struct is_map_like
      : mp11::mp_all<
          is_sequence_like<T>,
          mp11::mp_valid_and_true<detail::is_value_type_pair, T>,
          is_string_like<detail::key_type<T>>,
          mp11::mp_valid_and_true<detail::has_unique_keys, T>>
  { };
  
  template<class T>
  struct is_tuple_like
      : mp11::mp_valid_and_true<detail::has_positive_tuple_size, T>
  { };
  
  template<>
  struct is_null_like<std::nullptr_t>
      : std::true_type
  { };
  
  #ifndef BOOST_NO_CXX17_HDR_VARIANT
  template<>
  struct is_null_like<std::monostate>
      : std::true_type
  { };
  #endif // BOOST_NO_CXX17_HDR_VARIANT
  
  template<class T>
  struct is_described_class
      : mp11::mp_and<
          describe::has_describe_members<T>,
          mp11::mp_not< std::is_union<T> >,
          mp11::mp_empty<
              mp11::mp_eval_or<
                  mp11::mp_list<>, detail::described_non_public_members, T>>,
          mp11::mp_empty<
              mp11::mp_eval_or<mp11::mp_list<>, detail::described_bases, T>>>
  { };
  
  template<class T>
  struct is_described_enum
      : describe::has_describe_enumerators<T>
  { };
  
  BOOST_JSON_NS_END
  
  #endif // BOOST_JSON_IMPL_CONVERSION_HPP