113 lines
4.2 KiB
C++
113 lines
4.2 KiB
C++
#pragma once
|
|
//#include <fc/function.hpp>
|
|
#include <fc/future.hpp>
|
|
#include <functional>
|
|
#include <boost/preprocessor/repeat.hpp>
|
|
#include <boost/preprocessor/repetition/enum_binary_params.hpp>
|
|
#include <boost/preprocessor/repetition/enum_params.hpp>
|
|
#include <boost/preprocessor/repetition/enum_trailing_params.hpp>
|
|
#include <boost/preprocessor/facilities/empty.hpp>
|
|
|
|
namespace fc {
|
|
|
|
namespace detail {
|
|
struct identity_member {
|
|
#if BOOST_NO_VARIADIC_TEMPLATES
|
|
#define RPC_MEMBER_FUNCTOR(z,n,IS_CONST) \
|
|
template<typename R, typename C, typename P BOOST_PP_ENUM_TRAILING_PARAMS( n, typename A)> \
|
|
static std::function<R( BOOST_PP_ENUM_PARAMS(n,A) ) > \
|
|
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<typename R, typename C, typename P, typename... Args>
|
|
static std::function<R(Args...)> functor( P&& p, R (C::*mem_func)(Args...) ) {
|
|
return std::function<R(Args...)>([=](Args... args){ return (p->*mem_func)(args...); });
|
|
}
|
|
template<typename R, typename C, typename P, typename... Args>
|
|
static std::function<R(Args...)> functor( P&& p, R (C::*mem_func)(Args...)const ) {
|
|
return std::function<R(Args...)>([=](Args... args){ return (p->*mem_func)(args...); });
|
|
}
|
|
#endif
|
|
};
|
|
|
|
template< typename Interface, typename Transform = detail::identity_member >
|
|
struct vtable{};
|
|
|
|
template<typename ThisPtr>
|
|
struct vtable_visitor {
|
|
template<typename U>
|
|
vtable_visitor( U&& u ):_this( fc::forward<U>(u) ){}
|
|
|
|
template<typename Function, typename MemberPtr>
|
|
void operator()( const char* name, Function& memb, MemberPtr m )const {
|
|
memb = identity_member::functor( _this, m );
|
|
}
|
|
ThisPtr _this;
|
|
};
|
|
} // namespace detail
|
|
|
|
template<typename Interface, typename Transform = detail::identity_member >
|
|
class ptr {
|
|
public:
|
|
typedef detail::vtable<Interface,Transform> vtable_type;
|
|
|
|
ptr(){}
|
|
|
|
template<typename InterfaceType>
|
|
ptr( InterfaceType* p )
|
|
:_vtable( new vtable_type() ) {
|
|
_vtable->template visit_other<InterfaceType>( detail::vtable_visitor<InterfaceType*>(p) );
|
|
}
|
|
|
|
template<typename InterfaceType>
|
|
ptr( const fc::shared_ptr<InterfaceType>& p )
|
|
:_vtable( new vtable_type() ),_self(p){
|
|
_vtable->template visit_other<InterfaceType>( detail::vtable_visitor<InterfaceType*>(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 <boost/preprocessor/seq/for_each.hpp>
|
|
#include <boost/preprocessor/stringize.hpp>
|
|
|
|
#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<typename Transform> \
|
|
struct vtable<test,Transform> : public fc::retainable { \
|
|
vtable(){} \
|
|
BOOST_PP_SEQ_FOR_EACH( FC_STUB_VTABLE_DEFINE_MEMBER, CLASS, METHODS ) \
|
|
template<typename T, typename Visitor> \
|
|
void visit_other( Visitor&& v ){ \
|
|
BOOST_PP_SEQ_FOR_EACH( FC_STUB_VTABLE_DEFINE_VISIT_OTHER, CLASS, METHODS ) \
|
|
} \
|
|
template<typename Visitor> \
|
|
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
|