@@ -32,6 +32,9 @@ namespace boost {
32
32
namespace json {
33
33
namespace detail {
34
34
35
+ struct no_context
36
+ {};
37
+
35
38
#ifdef __cpp_lib_nonmember_container_access
36
39
using std::size;
37
40
#endif
@@ -317,14 +320,14 @@ using native_conversion_category = mp11::mp_cond<
317
320
std::is_same<T, string>, string_conversion_tag>;
318
321
319
322
// generic conversions
320
- template < class T >
323
+ template < class T , class Ctx >
321
324
using generic_conversion_category = mp11::mp_cond<
322
325
std::is_same<T, bool >, bool_conversion_tag,
323
326
std::is_integral<T>, integral_conversion_tag,
324
327
std::is_floating_point<T>, floating_point_conversion_tag,
325
328
is_null_like<T>, null_like_conversion_tag,
326
329
is_string_like<T>, string_like_conversion_tag,
327
- is_map_like<T>, map_like_conversion_tag,
330
+ is_map_like<T, Ctx>, map_like_conversion_tag,
328
331
is_sequence_like<T>, sequence_conversion_tag,
329
332
is_tuple_like<T>, tuple_conversion_tag,
330
333
is_described_class<T>, described_class_conversion_tag,
@@ -338,38 +341,92 @@ using generic_conversion_category = mp11::mp_cond<
338
341
template < class T >
339
342
using nested_type = typename T::type;
340
343
template < class T1 , class T2 >
341
- using conversion_category_impl_helper = mp11::mp_eval_if_not<
344
+ using conversion_category_helper = mp11::mp_eval_if_not<
342
345
std::is_same<detail::no_conversion_tag, T1>,
343
346
T1,
344
347
mp11::mp_eval_or_q, T1, mp11::mp_quote<nested_type>, T2>;
348
+
349
+ template < class Ctx >
350
+ using fix_context = mp11::mp_if< std::is_same<Ctx, no_context>, void , Ctx>;
351
+
352
+ template <class T , class Ctx >
353
+ using representation_or_void = mp11::mp_eval_or<void , represent_as_t , T, Ctx>;
354
+
355
+ template < class U >
356
+ using is_not_void = mp11::mp_bool< !std::is_same<void , U>::value >;
357
+
358
+ template < class T , class Ctxs >
359
+ struct representation_helper
360
+ {
361
+ using size = mp11::mp_size<Ctxs>;
362
+
363
+ template < class I >
364
+ using exists = mp11::mp_less<I, size>;
365
+
366
+ template < class Ctx >
367
+ using step = representation_or_void<T, Ctx>;
368
+ using reps = mp11::mp_transform<step, Ctxs>;
369
+ using r_index = mp11::mp_find_if< reps, is_not_void >;
370
+
371
+ using type = mp11::mp_eval_if<
372
+ mp11::mp_not< exists<r_index> >,
373
+ T,
374
+ mp11::mp_at, reps, r_index>;
375
+ };
376
+
377
+ template < class T , class Ctx >
378
+ struct conversion_representation_impl
379
+ : representation_helper< T, mp11::mp_list<Ctx, void > >
380
+ {};
381
+
382
+ template < class T >
383
+ struct conversion_representation_impl <T, no_context>
384
+ : representation_helper< T, mp11::mp_list<void > >
385
+ {};
386
+
387
+ template < class T , class ... Ctxs >
388
+ struct conversion_representation_impl < T, std::tuple<Ctxs...> >
389
+ : representation_helper< T, mp11::mp_list<remove_cvref<Ctxs>..., void > >
390
+ {};
391
+
392
+ template < class T , class Ctx >
393
+ using conversion_representation
394
+ = typename conversion_representation_impl<T, Ctx>::type;
395
+
345
396
template < class Ctx , class T , class Dir >
346
- struct conversion_category_impl
397
+ struct conversion_attrs
347
398
{
348
- using type = mp11::mp_fold<
399
+ using representation = conversion_representation<T, Ctx>;
400
+
401
+ using category = mp11::mp_fold<
349
402
mp11::mp_list<
350
- mp11::mp_defer<user_conversion_category, Ctx, T , Dir>,
351
- mp11::mp_defer<native_conversion_category, T >,
352
- mp11::mp_defer<generic_conversion_category, T >>,
403
+ mp11::mp_defer<user_conversion_category, Ctx, representation , Dir>,
404
+ mp11::mp_defer<native_conversion_category, representation >,
405
+ mp11::mp_defer<generic_conversion_category, representation, Ctx >>,
353
406
no_conversion_tag,
354
- conversion_category_impl_helper >;
407
+ conversion_category_helper >;
355
408
};
356
- template < class Ctx , class T , class Dir >
357
- using conversion_category =
358
- typename conversion_category_impl< Ctx, T, Dir >::type;
359
409
360
410
template < class T >
361
411
using any_conversion_tag = mp11::mp_not<
362
412
std::is_same< T, no_conversion_tag > >;
363
413
414
+ template < class Ctx , class T , class Dir >
415
+ using conversion_category = typename conversion_attrs<Ctx, T, Dir>::category;
416
+
364
417
template < class T , class Dir , class ... Ctxs >
365
- struct conversion_category_impl < std::tuple<Ctxs...>, T, Dir >
418
+ struct conversion_attrs < std::tuple<Ctxs...>, T, Dir >
366
419
{
420
+ using size = mp11::mp_size_t < sizeof ...(Ctxs) >;
367
421
using ctxs = mp11::mp_list< remove_cvref<Ctxs>... >;
368
- using cats = mp11::mp_list<
369
- conversion_category<remove_cvref<Ctxs>, T, Dir>... >;
370
422
371
423
template < class I >
372
- using exists = mp11::mp_less< I, mp11::mp_size<cats> >;
424
+ using exists = mp11::mp_less<I, size>;
425
+
426
+ using representation = conversion_representation< T, std::tuple<Ctxs...> >;
427
+
428
+ using cats = mp11::mp_list<
429
+ conversion_category<remove_cvref<Ctxs>, representation, Dir>... >;
373
430
374
431
using context2 = mp11::mp_find< cats, full_context_conversion_tag >;
375
432
using context1 = mp11::mp_find< cats, context_conversion_tag >;
@@ -379,14 +436,11 @@ struct conversion_category_impl< std::tuple<Ctxs...>, T, Dir >
379
436
exists<context1>, context1,
380
437
exists<context0>, context0,
381
438
mp11::mp_true, mp11::mp_find_if< cats, any_conversion_tag > >;
382
- using type = mp11::mp_eval_or<
439
+ using category = mp11::mp_eval_or<
383
440
no_conversion_tag,
384
441
mp11::mp_at, cats, index >;
385
442
};
386
443
387
- struct no_context
388
- {};
389
-
390
444
template <class T , class Dir >
391
445
using can_convert = mp11::mp_not<
392
446
std::is_same<
@@ -456,10 +510,10 @@ template< class T, class Dir, class... Ctxs >
456
510
struct supported_context < std::tuple<Ctxs...>, T, Dir >
457
511
{
458
512
using Ctx = std::tuple<Ctxs...>;
459
- using impl = conversion_category_impl <Ctx, T, Dir>;
460
- using index = typename impl ::index;
513
+ using Attrs = conversion_attrs <Ctx, T, Dir>;
514
+ using index = typename Attrs ::index;
461
515
using next_supported = supported_context<
462
- mp11::mp_at< typename impl ::ctxs, index >, T, Dir >;
516
+ mp11::mp_at< typename Attrs ::ctxs, index >, T, Dir >;
463
517
using type = typename next_supported::type;
464
518
465
519
static
@@ -508,12 +562,14 @@ struct is_sequence_like
508
562
mp11::mp_valid<detail::begin_iterator_category, T>>
509
563
{ };
510
564
511
- template <class T >
565
+ template <class T , class Ctx >
512
566
struct is_map_like
513
567
: mp11::mp_all<
514
568
is_sequence_like<T>,
515
569
mp11::mp_valid_and_true<detail::is_value_type_pair, T>,
516
- is_string_like<detail::key_type<T>>,
570
+ is_string_like<
571
+ detail::conversion_representation<
572
+ detail::remove_cvref< detail::key_type<T> >, Ctx>>,
517
573
mp11::mp_valid_and_true<detail::has_unique_keys, T>>
518
574
{ };
519
575
0 commit comments