@@ -196,6 +196,97 @@ tag_invoke(
196196 return T11 ( jv.to_number <int >() );
197197}
198198
199+ struct id
200+ {
201+ static constexpr char const * id1 = " Id#1" ;
202+ static constexpr char const * id2 = " Id#2" ;
203+
204+ std::size_t n;
205+ };
206+
207+ bool
208+ operator ==(id l, id r) noexcept
209+ {
210+ return l.n == r.n ;
211+ }
212+
213+ bool
214+ operator !=(id l, id r) noexcept
215+ {
216+ return l.n != r.n ;
217+ }
218+
219+ bool
220+ operator <(id l, id r) noexcept
221+ {
222+ return l.n < r.n ;
223+ }
224+
225+ struct id_string_repr
226+ {
227+ std::size_t n;
228+
229+ id_string_repr (id x) noexcept
230+ : n(x.n)
231+ {}
232+
233+ id_string_repr (boost::json::string_view sv)
234+ {
235+ if ( sv == boost::json::string_view (id::id1, 4 ) )
236+ n = 1 ;
237+ else if ( sv == boost::json::string_view (id::id2, 4 ) )
238+ n = 2 ;
239+ else
240+ throw std::runtime_error ( " unknown id" );
241+ }
242+
243+ operator id () const noexcept
244+ {
245+ return {n};
246+ }
247+
248+ operator boost::json::string_view () const noexcept
249+ {
250+ switch (n)
251+ {
252+ case 1 : return boost::json::string_view (id::id1, 4 );
253+ case 2 : return boost::json::string_view (id::id2, 4 );
254+ default : return boost::json::string_view (" unknown" );
255+ }
256+ }
257+ };
258+
259+ struct T12
260+ {
261+ id i;
262+ };
263+ BOOST_DESCRIBE_STRUCT (T12, (), (i))
264+
265+ struct as_string {};
266+
267+ struct int_as_string
268+ {
269+ std::string s;
270+
271+ int_as_string (int n) noexcept
272+ : s( std::to_string(n) )
273+ {}
274+
275+ int_as_string (boost::json::string_view sv)
276+ : s(sv)
277+ {}
278+
279+ operator int () const noexcept
280+ {
281+ return std::atoi ( s.data () );
282+ }
283+
284+ operator boost::json::string_view () const noexcept
285+ {
286+ return s;
287+ }
288+ };
289+
199290} // namespace value_to_test_ns
200291
201292namespace std
@@ -225,6 +316,18 @@ struct is_null_like<::value_to_test_ns::T1> : std::true_type { };
225316template <>
226317struct is_described_class <::value_to_test_ns::T7> : std::true_type { };
227318
319+ template <>
320+ struct represent_as <::value_to_test_ns::id>
321+ {
322+ using type = ::value_to_test_ns::id_string_repr;
323+ };
324+
325+ template <>
326+ struct represent_as <int , value_to_test_ns::as_string>
327+ {
328+ using type = ::value_to_test_ns::int_as_string;
329+ };
330+
228331template <class T , class = void >
229332struct can_apply_value_to
230333 : std::false_type
@@ -335,6 +438,19 @@ class value_to_test
335438 BOOST_TEST_CONV ( arr, ctx... );
336439 }
337440
441+ BOOST_TEST ((
442+ value_to< std::vector<value_to_test_ns::id> >(
443+ value{" Id#1" , " Id#2" , " Id#2" , " Id#1" }, ctx... )
444+ == std::vector<value_to_test_ns::id>{{1 }, {2 }, {2 }, {1 }} ));
445+ BOOST_TEST ((
446+ value_to< std::tuple<value_to_test_ns::id, int > >(
447+ value{" Id#1" , 12 }, ctx... )
448+ == std::tuple<value_to_test_ns::id, int >{{1 }, 12 } ));
449+ BOOST_TEST ((
450+ value_to< std::map<value_to_test_ns::id, int > >(
451+ value{ {" Id#1" , 42 }, {" Id#2" , 43 } }, ctx... )
452+ == std::map<value_to_test_ns::id, int >{ {{1 }, 42 }, {{2 }, 43 } } ));
453+
338454 // mismatched type
339455 BOOST_TEST_THROWS_WITH_LOCATION (
340456 value_to<std::string>( value (), ctx... ));
@@ -464,6 +580,11 @@ class value_to_test
464580 BOOST_TEST ( e1 == ::value_to_test_ns::E1 ::b );
465581 }
466582
583+ BOOST_TEST ((
584+ value_to<value_to_test_ns::T12>(
585+ value (object{ {" i" , " Id#1" } }), ctx... ).i
586+ == value_to_test_ns::T12{ {1 } }.i ));
587+
467588 BOOST_TEST_THROWS_WITH_LOCATION (
468589 value_to<::value_to_test_ns::E1 >( value (1 ), ctx... ));
469590 BOOST_TEST_THROWS_WITH_LOCATION (
@@ -506,6 +627,12 @@ class value_to_test
506627 value_to< std::nullopt_t >(value ());
507628 BOOST_TEST_THROWS_WITH_LOCATION (
508629 value_to< std::nullopt_t >( jv, ctx... ));
630+
631+ BOOST_TEST ((
632+ value_to< std::optional<value_to_test_ns::id> >(
633+ value (" Id#1" ), ctx... )
634+ == std::optional<value_to_test_ns::id>(
635+ value_to_test_ns::id{1 } ) ));
509636#endif
510637 }
511638
@@ -550,6 +677,10 @@ class value_to_test
550677 using V_T3_T1 = Variant<value_to_test_ns::T3, value_to_test_ns::T1>;
551678 auto v_t3_t1 = value_to<V_T3_T1>( jv, ctx... );
552679 BOOST_TEST ( v_t3_t1.index () == 1 );
680+
681+ BOOST_TEST ((
682+ value_to< Variant<value_to_test_ns::id> >( value (" Id#2" ), ctx... )
683+ == Variant<value_to_test_ns::id>( value_to_test_ns::id{2 } )));
553684 }
554685
555686 template < class ... Context >
@@ -757,6 +888,13 @@ class value_to_test
757888 testUserConversion ( Context const & ... ctx )
758889 {
759890 value_to<value_to_test_ns::T2>( value (" T2" ), ctx... );
891+
892+ auto id = value_to<value_to_test_ns::id>(
893+ value (" Id#1" ), ctx... );
894+ BOOST_TEST ( id.n == 1 );
895+ id = value_to<value_to_test_ns::id>(
896+ value (" Id#2" ), ctx... );
897+ BOOST_TEST ( id.n == 2 );
760898 }
761899
762900 void
@@ -769,6 +907,19 @@ class value_to_test
769907 value_to<value_to_test_ns::T9>(
770908 value (), value_to_test_ns::custom_context () ),
771909 system::system_error);
910+
911+ BOOST_TEST ((
912+ value_to< std::map<int , int > >(
913+ value{ {" 1" , " 2" }, {" 2" , " 4" }, {" 3" , " 8" } },
914+ value_to_test_ns::as_string () )
915+ == std::map<int , int >{ {1 ,2 }, {2 ,4 }, {3 ,8 } } ));
916+ BOOST_TEST ((
917+ value_to< std::map<int , int > >(
918+ value{ {" 1" , " 2" }, {" 2" , " 4" }, {" 3" , " 6" } },
919+ std::make_tuple (
920+ value_to_test_ns::as_string (),
921+ value_to_test_ns::custom_context () ))
922+ == std::map<int , int >{ {1 ,2 }, {2 ,4 }, {3 ,6 } } ));
772923 }
773924
774925 struct run_templated_tests
0 commit comments