#pragma once #include #include #include #include #include #include #include #include #include namespace fc { 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 > struct vtable : public std::enable_shared_from_this> { private: vtable(); }; template struct vtable_copy_visitor { typedef OtherType other_type; vtable_copy_visitor( OtherType& s):_source( s ){} template void operator()( const char* name, std::function& memb, MemberPtr m )const { OtherType* src = &_source; memb = [src,m]( Args... args ){ wdump( (uint64_t(src) ) ); return (src->*m)(args...); }; } OtherType& _source; }; template class api { public: typedef vtable vtable_type; api() :_vtable( std::make_shared() ) {} /** T is anything with pointer semantics */ template api( const T& p ) :_vtable( std::make_shared() ) { _data = std::make_shared(p); T& ptr = boost::any_cast(*_data); auto& pointed_at = *ptr; typedef typename std::remove_reference::type source_vtable_type; _vtable->template visit_other( vtable_copy_visitor(pointed_at) ); } api( const api& cpy ) :_vtable(cpy._vtable),_data(cpy._data) { } friend bool operator == ( const api& a, const api& b ) { return a._data == b._data && a._vtable == b._vtable; } friend bool operator != ( const api& a, const api& b ) { return !(a._data == b._data && a._vtable == b._vtable); } vtable_type& operator*()const { wdump((uint64_t(this))); assert(_vtable); FC_ASSERT( _vtable ); return *_vtable; } vtable_type* operator->()const { assert(_vtable); FC_ASSERT( _vtable ); return _vtable.get(); } void test(); protected: std::shared_ptr _vtable; std::shared_ptr _data; }; } #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 ) \ { typedef typename Visitor::other_type OtherType; \ v( BOOST_PP_STRINGIZE(elem), elem, &OtherType::elem ); } #define FC_API_VTABLE_DEFINE_VISIT( r, data, elem ) \ v( BOOST_PP_STRINGIZE(elem), elem ); #define FC_API( CLASS, METHODS ) \ namespace fc { \ template \ struct vtable : public std::enable_shared_from_this> { \ 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