#pragma once //#include #include #include #include #include #include #include #include #include namespace fc { namespace detail { struct identity_member { #ifdef BOOST_NO_VARIADIC_TEMPLATES #define RPC_MEMBER_FUNCTOR(z,n,IS_CONST) \ template \ static std::function \ functor( P p, R (C::*mem_func)(BOOST_PP_ENUM_PARAMS(n,A)) IS_CONST ){ \ return [=](BOOST_PP_ENUM_BINARY_PARAMS(n,A,a)){ return (p->*mem_func)(BOOST_PP_ENUM_PARAMS(n,a)); }; \ } BOOST_PP_REPEAT( 8, RPC_MEMBER_FUNCTOR, const ) BOOST_PP_REPEAT( 8, RPC_MEMBER_FUNCTOR, BOOST_PP_EMPTY() ) #undef RPC_MEMBER_FUNCTOR #else 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...); }); } #endif }; 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 ptr { public: typedef detail::vtable vtable_type; ptr(){} template ptr( InterfaceType* p ) :_vtable( new vtable_type() ) { _vtable->template visit_other( detail::vtable_visitor(p) ); } template ptr( 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_STUB_VTABLE_DEFINE_MEMBER( r, data, elem ) \ decltype(Transform::functor( (data*)nullptr, &data::elem)) elem; #define FC_STUB_VTABLE_DEFINE_VISIT_OTHER( r, data, elem ) \ v( BOOST_PP_STRINGIZE(elem), elem, &T::elem ); #define FC_STUB_VTABLE_DEFINE_VISIT( r, data, elem ) \ v( BOOST_PP_STRINGIZE(elem), elem ); #define FC_STUB( CLASS, METHODS ) \ namespace fc { namespace detail { \ template \ struct vtable : public fc::retainable { \ vtable(){} \ BOOST_PP_SEQ_FOR_EACH( FC_STUB_VTABLE_DEFINE_MEMBER, CLASS, METHODS ) \ template \ void visit_other( Visitor&& v ){ \ BOOST_PP_SEQ_FOR_EACH( FC_STUB_VTABLE_DEFINE_VISIT_OTHER, CLASS, METHODS ) \ } \ template \ void visit( Visitor&& v ){ \ BOOST_PP_SEQ_FOR_EACH( FC_STUB_VTABLE_DEFINE_VISIT, CLASS, METHODS ) \ } \ }; \ } } //#undef FC_STUB_VTABLE_DEFINE_MEMBER //#undef FC_STUB_VTABLE_DEFINE_VISIT