#include <cstddef>
#include <boost/function_types/function_pointer.hpp>
#include <boost/function_types/member_function_pointer.hpp>
#include <boost/config.hpp>
#include <boost/detail/workaround.hpp>
#include <boost/utility/addressof.hpp>
#include <boost/mpl/at.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/mpl/joint_view.hpp>
#include <boost/mpl/single_view.hpp>
#include <boost/mpl/transform_view.hpp>
#include <boost/preprocessor/seq/seq.hpp>
#include <boost/preprocessor/seq/enum.hpp>
#include <boost/preprocessor/seq/elem.hpp>
#include <boost/preprocessor/seq/size.hpp>
#include <boost/preprocessor/tuple/elem.hpp>
#include <boost/preprocessor/arithmetic/dec.hpp>
#include <boost/preprocessor/arithmetic/inc.hpp>
#include <boost/preprocessor/facilities/empty.hpp>
#include <boost/preprocessor/facilities/identity.hpp>
#include <boost/preprocessor/punctuation/comma_if.hpp>
#include <boost/preprocessor/iteration/local.hpp>
#include <boost/preprocessor/repetition/enum.hpp>
#include <boost/preprocessor/repetition/enum_params.hpp>
#include <boost/preprocessor/repetition/enum_binary_params.hpp>
#include <boost/preprocessor/repetition/enum_trailing_params.hpp>
#include "detail/param_type.hpp"
namespace example
{
namespace ft = boost::function_types;
namespace mpl = boost::mpl;
using namespace mpl::placeholders;
template<typename T, typename Seq>
struct concat_view
: mpl::joint_view<mpl::single_view<T>, Seq>
{ };
template<typename Inf>
struct vtable_entry
: ft::function_pointer
< concat_view< typename Inf::result, mpl::transform_view<
typename Inf::params, param_type<_> > > >
{ };
template<typename Inf, typename Tag>
struct member
{
typedef typename ft::member_function_pointer
< concat_view<typename Inf::result,typename Inf::params>,Tag
>::type
mem_func_ptr;
typedef typename mpl::at_c<typename Inf::params,0>::type context;
template<mem_func_ptr MemFuncPtr>
static typename Inf::result wrap(void* c)
{
return (reinterpret_cast<context*>(c)->*MemFuncPtr)();
}
template<mem_func_ptr MemFuncPtr, typename T0>
static typename Inf::result wrap(void* c, T0 a0)
{
return (reinterpret_cast<context*>(c)->*MemFuncPtr)(a0);
}
template<mem_func_ptr MemFuncPtr, typename T0, typename T1>
static typename Inf::result wrap(void* c, T0 a0, T1 a1)
{
return (reinterpret_cast<context*>(c)->*MemFuncPtr)(a0,a1);
}
#define BOOST_PP_LOCAL_MACRO(n) \
template<mem_func_ptr MemFuncPtr, BOOST_PP_ENUM_PARAMS(n,typename T)> \
static typename Inf::result wrap(void* c, \
BOOST_PP_ENUM_BINARY_PARAMS(n,T,a)) \
{ \
return (reinterpret_cast<context*>(c)->*MemFuncPtr)( \
BOOST_PP_ENUM_PARAMS(n,a) ); \
}
#define BOOST_PP_LOCAL_LIMITS (3,BOOST_FT_MAX_ARITY-1)
#include BOOST_PP_LOCAL_ITERATE()
};
template<typename Inf, std::size_t Index>
struct param
: param_type< typename mpl::at_c< typename Inf::params,Index>::type >
{ };
}
#define BOOST_EXAMPLE_INTERFACE(name,def) \
class name \
{ \
struct vtable \
{ \
BOOST_EXAMPLE_INTERFACE__MEMBERS(def,VTABLE) \
}; \
\
vtable const * ptr_vtable; \
void * ptr_that; \
\
template<class T> struct vtable_holder \
{ \
static vtable const val_vtable; \
}; \
\
public: \
\
template<class T> \
inline name (T & that) \
: ptr_vtable(& vtable_holder<T>::val_vtable) \
, ptr_that(boost::addressof(that)) \
{ } \
\
BOOST_EXAMPLE_INTERFACE__MEMBERS(def,FUNCTION) \
}; \
\
template<typename T> \
name ::vtable const name ::vtable_holder<T>::val_vtable \
= { BOOST_EXAMPLE_INTERFACE__MEMBERS(def,INIT_VTABLE) }
#ifdef BOOST_PP_NIL
BOOST_EXAMPLE_INTERFACE( interface_x,
(( a_func, (void)(int), const_qualified ))
(( another_func, (int), non_const ))
);
class interface_x
{
struct vtable
{
template<typename T = void*> struct inf0
{
typedef void result;
typedef ::boost::mpl::vector< T, int > params;
};
::example::vtable_entry<inf0<> >::type func0;
template<typename T = void*> struct inf1
{
typedef int result;
typedef ::boost::mpl::vector< T > params;
};
::example::vtable_entry<inf1<> >::type func1;
};
vtable const * ptr_vtable;
void * ptr_that;
template<class T> struct vtable_holder
{
static vtable const val_vtable;
};
public:
template<class T>
inline interface_x (T & that)
: ptr_vtable(& vtable_holder<T>::val_vtable)
, ptr_that(boost::addressof(that))
{ }
inline vtable::inf0<> ::result a_func (
::example::param<vtable::inf0<>,1>::type p0) const
{
return ptr_vtable-> func0(ptr_that , p0);
}
inline vtable::inf1<> ::result another_func ()
{
return ptr_vtable-> func1(ptr_that );
}
};
template<typename T>
interface_x ::vtable const interface_x ::vtable_holder<T>::val_vtable =
{
& ::example::member< vtable::inf0<T>, ::example::ft:: const_qualified >
::template wrap < &T:: a_func >
, & ::example::member< vtable::inf1<T>, ::example::ft:: non_const >
::template wrap < &T:: another_func >
};
#endif
#define BOOST_EXAMPLE_INTERFACE__MEMBERS(seq,macro) \
BOOST_PP_REPEAT(BOOST_PP_SEQ_SIZE(seq), \
BOOST_EXAMPLE_INTERFACE__ ## macro,seq)
#define BOOST_EXAMPLE_INTERFACE__VTABLE(z,i,seq) \
BOOST_EXAMPLE_INTERFACE__VTABLE_I(z,i, \
BOOST_PP_TUPLE_ELEM(3,1,BOOST_PP_SEQ_ELEM(i,seq)))
#define BOOST_EXAMPLE_INTERFACE__VTABLE_I(z,i,seq) \
BOOST_EXAMPLE_INTERFACE__VTABLE_II(z,i, \
BOOST_PP_SEQ_HEAD(seq),(T)BOOST_PP_SEQ_TAIL(seq))
#define BOOST_EXAMPLE_INTERFACE__VTABLE_II(z,i,result_type,param_types) \
template<typename T = void*> \
struct BOOST_PP_CAT(inf,i) \
{ \
typedef result_type result; \
typedef ::boost::mpl::vector< BOOST_PP_SEQ_ENUM(param_types) > params; \
}; \
::example::vtable_entry<BOOST_PP_CAT(inf,i)<> >::type BOOST_PP_CAT(func,i);
#define BOOST_EXAMPLE_INTERFACE__INIT_VTABLE(z,i,seq) \
BOOST_EXAMPLE_INTERFACE__INIT_VTABLE_I(i,seq,BOOST_PP_CAT(func,i), \
BOOST_PP_SEQ_ELEM(i,seq))
#define BOOST_EXAMPLE_INTERFACE__INIT_VTABLE_I(i,seq,func,desc) \
BOOST_PP_COMMA_IF(i) & ::example::member< BOOST_PP_CAT(vtable::inf,i)<T>, \
::example::ft:: BOOST_PP_TUPLE_ELEM(3,2,desc) >::template wrap \
< &T:: BOOST_PP_TUPLE_ELEM(3,0,desc) >
#define BOOST_EXAMPLE_INTERFACE__FUNCTION(z,i,seq) \
BOOST_EXAMPLE_INTERFACE__FUNCTION_I(z,i,BOOST_PP_SEQ_ELEM(i,seq))
#define BOOST_EXAMPLE_INTERFACE__FUNCTION_I(z,i,desc) \
BOOST_EXAMPLE_INTERFACE__FUNCTION_II(z,i, \
BOOST_PP_TUPLE_ELEM(3,0,desc), \
BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(BOOST_PP_TUPLE_ELEM(3,1,desc))), \
BOOST_PP_CAT(vtable::inf,i)<>, \
BOOST_PP_CAT(BOOST_EXAMPLE_INTERFACE___,BOOST_PP_TUPLE_ELEM(3,2,desc)) \
)
#define BOOST_EXAMPLE_INTERFACE__FUNCTION_II(z,i,name,arity,types,cv) \
inline types ::result name \
(BOOST_PP_ENUM_ ## z (arity,BOOST_EXAMPLE_INTERFACE__PARAM,types)) cv() \
{ \
return ptr_vtable-> BOOST_PP_CAT(func,i)(ptr_that \
BOOST_PP_ENUM_TRAILING_PARAMS_Z(z,arity,p)); \
}
#define BOOST_EXAMPLE_INTERFACE__PARAM(z,j,types) \
::example::param<types,BOOST_PP_INC(j)>::type BOOST_PP_CAT(p,j)
#define BOOST_EXAMPLE_INTERFACE___const_qualified BOOST_PP_IDENTITY(const)
#define BOOST_EXAMPLE_INTERFACE___non_const BOOST_PP_EMPTY