@@ -364,18 +364,49 @@ namespace tao
364364 }
365365 };
366366
367- template < typename K, typename B >
367+ template < typename K, typename T, typename U >
368368 struct factory_type
369- : public factory_name< K >,
370- public B
369+ : public factory_name< K >
371370 {
371+ static const std::type_info* type ()
372+ {
373+ return &typeid ( T );
374+ }
375+
376+ template < template < typename ... > class Traits , typename Base >
377+ static std::shared_ptr< U > as ( const basic_value< Traits, Base >& v )
378+ {
379+ using R = typename Traits< std::shared_ptr< T > >::template with_base< U >;
380+ return R::as ( v );
381+ }
382+
383+ template < template < typename ... > class Traits , typename Base >
384+ static void assign ( basic_value< Traits, Base >& v, const std::shared_ptr< U >& p )
385+ {
386+ using R = typename Traits< std::shared_ptr< T > >::template with_base< U >;
387+ R::assign ( v, p );
388+ }
389+
390+ template < template < typename ... > class Traits , typename Consumer >
391+ static void produce ( Consumer& consumer, const std::shared_ptr< U >& p )
392+ {
393+ using R = typename Traits< std::shared_ptr< T > >::template with_base< U >;
394+ R::template produce< Traits >( consumer, p );
395+ }
396+
397+ template < template < typename ... > class Traits , typename Producer >
398+ static std::shared_ptr< U > consume ( Producer& producer )
399+ {
400+ using R = typename Traits< std::shared_ptr< T > >::template with_base< U >;
401+ return R::template consume< Traits >( producer );
402+ }
372403 };
373404
374405 template < typename K, typename T >
375406 struct factory_temp
376407 {
377- template < typename U, template < typename ... > class Traits >
378- using type = factory_type< K, typename Traits< std::shared_ptr< T > >:: template with_base< U > >;
408+ template < typename U >
409+ using bind = factory_type< K, T, U >;
379410 };
380411
381412 template < typename U, typename ... Ts >
@@ -392,11 +423,24 @@ namespace tao
392423 F function;
393424 };
394425
426+ template < typename F >
427+ struct entry2
428+ {
429+ entry2 ( F c, const std::string& n )
430+ : function( c ),
431+ name ( n )
432+ {
433+ }
434+
435+ F function;
436+ std::string name;
437+ };
438+
395439 template < typename V, template < typename ... > class Traits , typename Base, typename F >
396440 static bool emplace_as ( std::map< std::string, entry< F > >& m )
397441 {
398- using T = typename V::template type < U, Traits >;
399- m.emplace ( T ::name (), entry< F >( &T ::template as< Traits, Base > ) );
442+ using W = typename V::template bind < U >;
443+ m.emplace ( W ::name (), entry< F >( &W ::template as< Traits, Base > ) );
400444 return true ;
401445 }
402446
@@ -422,6 +466,65 @@ namespace tao
422466 }
423467 return i->second .function ( b->second );
424468 }
469+
470+ template < typename V, template < typename ... > class Traits , typename Base, typename F >
471+ static bool emplace_assign ( std::map< const std::type_info*, entry2< F >, json::internal::type_info_less >& m )
472+ {
473+ using W = typename V::template bind< U >;
474+ m.emplace ( W::type (), entry2< F >( &W::template assign< Traits, Base >, W::name () ) );
475+ return true ;
476+ }
477+
478+ template < template < typename ... > class Traits , typename Base >
479+ static void assign ( basic_value< Traits, Base >& v, const std::shared_ptr< U >& p )
480+ {
481+ using F = void ( * )( basic_value< Traits, Base >&, const std::shared_ptr< U >& );
482+ static const std::map< const std::type_info*, entry2< F >, json::internal::type_info_less > m = []() {
483+ std::map< const std::type_info*, entry2< F >, json::internal::type_info_less > t;
484+ (void )json::internal::swallow{ emplace_assign< Ts, Traits, Base >( t )... };
485+ assert ( t.size () == sizeof ...( Ts ) );
486+ return t;
487+ }();
488+
489+ const auto i = m.find ( &typeid ( *p ) );
490+ if ( i == m.end () ) {
491+ throw std::runtime_error ( " unknown factory type " + TAO_JSON_PEGTL_NAMESPACE::internal::demangle ( typeid ( *p ).name () ) ); // NOLINT
492+ }
493+ i->second .function ( v, p );
494+ v = {
495+ { i->second .name , std::move ( v ) }
496+ };
497+ }
498+
499+ template < typename V, template < typename ... > class Traits , typename Consumer, typename F >
500+ static bool emplace_produce ( std::map< const std::type_info*, entry2< F >, json::internal::type_info_less >& m )
501+ {
502+ using W = typename V::template bind< U >;
503+ m.emplace ( W::type (), entry2< F >( &W::template produce< Traits, Consumer >, W::name () ) );
504+ return true ;
505+ }
506+
507+ template < template < typename ... > class Traits , typename Consumer >
508+ static void produce ( Consumer& consumer, const std::shared_ptr< U >& p )
509+ {
510+ using F = void ( * )( Consumer&, const std::shared_ptr< U >& );
511+ static const std::map< const std::type_info*, entry2< F >, json::internal::type_info_less > m = []() {
512+ std::map< const std::type_info*, entry2< F >, json::internal::type_info_less > t;
513+ (void )json::internal::swallow{ emplace_produce< Ts, Traits, Consumer >( t )... };
514+ assert ( t.size () == sizeof ...( Ts ) );
515+ return t;
516+ }();
517+
518+ const auto i = m.find ( &typeid ( *p ) );
519+ if ( i == m.end () ) {
520+ throw std::runtime_error ( " unknown factory type " + TAO_JSON_PEGTL_NAMESPACE::internal::demangle ( typeid ( *p ).name () ) ); // NOLINT
521+ }
522+ consumer.begin_object ( 1 );
523+ consumer.key ( i->second .name );
524+ i->second .function ( consumer, p );
525+ consumer.member ();
526+ consumer.end_object ( 1 );
527+ }
425528 };
426529
427530 } // namespace binding
0 commit comments