@@ -196,6 +196,97 @@ tag_invoke(
196196 return T11 ( jv.to_number <int >() );
197197}
198198
199+ struct id
200+ {
201+ static constexpr auto & id1 = " Id#1" ;
202+ static constexpr auto & 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 ( std::equal ( sv.begin (), sv.end (), id::id1) )
236+ n = 1 ;
237+ else if ( std::equal ( sv.begin (), sv.end (), id::id2) )
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);
253+ case 2 : return boost::json::string_view (id::id2);
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,11 @@ 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>( {1 } ) ));
509635#endif
510636 }
511637
@@ -550,6 +676,10 @@ class value_to_test
550676 using V_T3_T1 = Variant<value_to_test_ns::T3, value_to_test_ns::T1>;
551677 auto v_t3_t1 = value_to<V_T3_T1>( jv, ctx... );
552678 BOOST_TEST ( v_t3_t1.index () == 1 );
679+
680+ BOOST_TEST ((
681+ value_to< Variant<value_to_test_ns::id> >( value (" Id#2" ), ctx... )
682+ == Variant<value_to_test_ns::id>( value_to_test_ns::id{2 } )));
553683 }
554684
555685 template < class ... Context >
@@ -757,6 +887,13 @@ class value_to_test
757887 testUserConversion ( Context const & ... ctx )
758888 {
759889 value_to<value_to_test_ns::T2>( value (" T2" ), ctx... );
890+
891+ auto id = value_to<value_to_test_ns::id>(
892+ value (" Id#1" ), ctx... );
893+ BOOST_TEST ( id.n == 1 );
894+ id = value_to<value_to_test_ns::id>(
895+ value (" Id#2" ), ctx... );
896+ BOOST_TEST ( id.n == 2 );
760897 }
761898
762899 void
@@ -769,6 +906,19 @@ class value_to_test
769906 value_to<value_to_test_ns::T9>(
770907 value (), value_to_test_ns::custom_context () ),
771908 system::system_error);
909+
910+ BOOST_TEST ((
911+ value_to< std::map<int , int > >(
912+ value{ {" 1" , " 2" }, {" 2" , " 4" }, {" 3" , " 8" } },
913+ value_to_test_ns::as_string () )
914+ == std::map<int , int >{ {1 ,2 }, {2 ,4 }, {3 ,8 } } ));
915+ BOOST_TEST ((
916+ value_to< std::map<int , int > >(
917+ value{ {" 1" , " 2" }, {" 2" , " 4" }, {" 3" , " 6" } },
918+ std::make_tuple (
919+ value_to_test_ns::as_string (),
920+ value_to_test_ns::custom_context () ))
921+ == std::map<int , int >{ {1 ,2 }, {2 ,4 }, {3 ,6 } } ));
772922 }
773923
774924 struct run_templated_tests
0 commit comments