#pragma once #include #include #include #include #include #include #include #include namespace fc { namespace detail { struct identity_member { template static std::function functor( P&& p, R (C::*mem_func)(Args...) ) { return std::function([=](Args... args){ return (p->*mem_func)(args...); }); } template static std::function functor( P&& p, R (C::*mem_func)(Args...)const ) { return std::function([=](Args... args){ return (p->*mem_func)(args...); }); } }; template< typename Interface, typename Transform = detail::identity_member > struct vtable{}; template struct vtable_visitor { template vtable_visitor( U&& u ):_this( fc::forward(u) ){} template void operator()( const char* name, Function& memb, MemberPtr m )const { memb = identity_member::functor( _this, m ); } ThisPtr _this; }; } // namespace detail template class api { public: typedef detail::vtable vtable_type; api(){} template api( InterfaceType* p ) :_vtable( new vtable_type() ) { _vtable->template visit_other( detail::vtable_visitor(p) ); } template api( const fc::shared_ptr& p ) :_vtable( new vtable_type() ),_self(p){ _vtable->template visit_other( detail::vtable_visitor(p.get()) ); } //vtable_type& operator*() { return *_vtable; } vtable_type& operator*()const { return *_vtable; } //vtable_type* operator->() { return _vtable.get(); } vtable_type* operator->()const { return _vtable.get(); } protected: fc::shared_ptr< vtable_type > _vtable; fc::shared_ptr< fc::retainable > _self; }; } #include #include #define FC_API_VTABLE_DEFINE_MEMBER( r, data, elem ) \ decltype(Transform::functor( (data*)nullptr, &data::elem)) elem; #define FC_API_VTABLE_DEFINE_VISIT_OTHER( r, data, elem ) \ v( BOOST_PP_STRINGIZE(elem), elem, &T::elem ); #define FC_API_VTABLE_DEFINE_VISIT( r, data, elem ) \ v( BOOST_PP_STRINGIZE(elem), elem ); #define FC_API( CLASS, METHODS ) \ namespace fc { namespace detail { \ template \ struct vtable : public fc::retainable { \ vtable(){} \ BOOST_PP_SEQ_FOR_EACH( FC_API_VTABLE_DEFINE_MEMBER, CLASS, METHODS ) \ template \ void visit_other( Visitor&& v ){ \ BOOST_PP_SEQ_FOR_EACH( FC_API_VTABLE_DEFINE_VISIT_OTHER, CLASS, METHODS ) \ } \ template \ void visit( Visitor&& v ){ \ BOOST_PP_SEQ_FOR_EACH( FC_API_VTABLE_DEFINE_VISIT, CLASS, METHODS ) \ } \ }; \ } } //#undef FC_API_VTABLE_DEFINE_MEMBER //#undef FC_API_VTABLE_DEFINE_VISIT