28 #ifndef INCLUDED_GenericCaller_h_GUID_C49A7DEE_89E6_478D_627A_CFFB9ED39EAC
29 #define INCLUDED_GenericCaller_h_GUID_C49A7DEE_89E6_478D_627A_CFFB9ED39EAC
35 #include <boost/preprocessor/cat.hpp>
36 #include <boost/preprocessor/if.hpp>
37 #include <boost/preprocessor/enum.hpp>
38 #include <boost/preprocessor/enum_params.hpp>
39 #include <boost/preprocessor/repeat.hpp>
40 #include <boost/preprocessor/facilities/empty.hpp>
42 #include <boost/function_types/function_arity.hpp>
43 #include <boost/function_types/result_type.hpp>
44 #include <boost/function_types/parameter_types.hpp>
45 #include <boost/type_traits/is_void.hpp>
46 #include <boost/type_traits/is_same.hpp>
47 #include <boost/type_traits/is_pointer.hpp>
48 #include <boost/type_traits/is_function.hpp>
49 #include <boost/type_traits/remove_cv.hpp>
50 #include <boost/type_traits/remove_reference.hpp>
51 #include <boost/type_traits/remove_pointer.hpp>
53 #include <boost/mpl/at.hpp>
54 #include <boost/mpl/int.hpp>
55 #include <boost/mpl/next_prior.hpp>
57 #include <boost/static_assert.hpp>
62 #ifndef OSVR_UTIL_CALLER_MAX_ARITY
63 #define OSVR_UTIL_CALLER_MAX_ARITY 3
68 #ifndef OSVR_DOXYGEN_EXTERNAL
69 namespace functor_trampolines {
70 #endif // ifndef OSVR_DOXYGEN_EXTERNAL
86 BOOST_CONSTEXPR_OR_CONST this_last_t
this_last = {};
92 #ifndef OSVR_DOXYGEN_EXTERNAL
99 typedef typename boost::function_types::parameter_types<F>::type
104 typename boost::mpl::at<ParamTypes,
117 template <
typename ThisLocation,
int Arity,
int Return>
121 #define OSVR_PARAM_STEM p
125 #define OSVR_MAKE_PARAMLIST(Z, N, unused) \
126 typename param_at<FPtr, N>::type BOOST_PP_CAT(OSVR_PARAM_STEM, N)
131 #define OSVR_RETURNTYPE(R) \
132 BOOST_PP_IF(R, typename boost::function_types::result_type<FPtr>::type, \
138 #define OSVR_RETURNSTATEMENT(R) BOOST_PP_IF(R, return, BOOST_PP_EMPTY())
145 #define OSVR_MAKE_CALLERS(Z, ARITY, RETURNS) \
146 template <> struct Caller<this_last_t, ARITY, RETURNS> { \
147 template <typename FPtr, typename F> struct Specialized { \
148 static OSVR_RETURNTYPE(RETURNS) \
149 call(BOOST_PP_ENUM(ARITY, OSVR_MAKE_PARAMLIST, ~) \
150 BOOST_PP_COMMA_IF(ARITY) void *functor) { \
151 F *o = static_cast<F *>(functor); \
152 OSVR_RETURNSTATEMENT(RETURNS) (*o)( \
153 BOOST_PP_ENUM_PARAMS(ARITY, OSVR_PARAM_STEM)); \
157 template <> struct Caller<this_first_t, ARITY, RETURNS> { \
158 template <typename FPtr, typename F> \
159 static OSVR_RETURNTYPE(RETURNS) \
160 call(void *functor BOOST_PP_COMMA_IF(ARITY) \
161 BOOST_PP_ENUM(ARITY, OSVR_MAKE_PARAMLIST, ~)) { \
162 F *o = static_cast<F *>(functor); \
163 OSVR_RETURNSTATEMENT(RETURNS) (*o)( \
164 BOOST_PP_ENUM_PARAMS(ARITY, OSVR_PARAM_STEM)); \
172 #undef OSVR_MAKE_CALLERS
173 #undef OSVR_RETURNSTATEMENT
174 #undef OSVR_RETURNTYPE
175 #undef OSVR_MAKE_PARAMLIST
176 #undef OSVR_PARAM_STEM
177 template <
typename FunctionPtr,
typename FunctionObjectType,
181 typename ThisLocation>
184 typedef typename boost::remove_cv<
185 typename boost::remove_reference<ThisLocation>::type>
::type
188 BOOST_STATIC_ASSERT_MSG(
193 "ThisLocation must be either this_last_t or this_first_t");
194 BOOST_STATIC_ASSERT_MSG(
195 !(boost::is_pointer<FunctionObjectType>::value),
196 "FunctionObjectType must be the type of your function "
198 BOOST_STATIC_ASSERT_MSG(
199 boost::is_function<
typename boost::remove_pointer<
200 FunctionPtr>::
type>::value &&
201 boost::is_pointer<FunctionPtr>::value,
202 "FunctionPtr must be a function pointer type");
203 #endif // OSVR_DOXYGEN
207 typedef typename boost::mpl::prior<
208 boost::function_types::function_arity<FunctionPtr> >
::type
213 boost::is_void<
typename boost::function_types::result_type<
215 boost::mpl::int_<0>, boost::mpl::int_<1> >::type
Returns;
222 typedef typename GeneralResult::template Specialized<
223 FunctionPtr, FunctionObjectType>
type;
226 #endif // ifndef OSVR_DOXYGEN_EXTERNAL
239 template <
typename FunctionPtr,
typename FunctionObjectType,
240 typename ThisLocation>
243 ThisLocation>::type {};
257 template <
typename FunctionPtr,
typename FunctionObjectType,
258 typename ThisLocation>
259 inline FunctionPtr getCaller() {
262 return &CallerType::call;
272 template <
typename FunctionPtr,
typename FunctionObjectType,
273 typename ThisLocation>
275 getCaller( ThisLocation
const &) {
276 return getCaller<FunctionPtr, FunctionObjectType, ThisLocation>();
292 template <
typename FunctionPtr,
typename FunctionObjectType,
293 typename ThisLocation>
294 inline FunctionPtr getCaller( FunctionObjectType
const *, ThisLocation
const &) {
297 return getCaller<FunctionPtr, FunctionObjectType, ThisLocation>();
299 #ifndef OSVR_DOXYGEN_EXTERNAL
303 using functor_trampolines::getCaller;
304 using functor_trampolines::GenericCaller;
306 using functor_trampolines::this_first_t;
308 using functor_trampolines::this_last_t;
310 #endif // ifndef OSVR_DOXYGEN_EXTERNAL
315 #endif // INCLUDED_GenericCaller_h_GUID_C49A7DEE_89E6_478D_627A_CFFB9ED39EAC
detail::Caller< UnqualifiedThisLocation, Arity::value, Returns::value > GeneralResult
Computed intermediate result.
BOOST_CONSTEXPR_OR_CONST this_last_t this_last
Pass as an argument to a getCaller() overload to indicate the last parameter of the function contains...
Tag type indicating the first parameter of the function contains the "this" pointer.
boost::remove_cv< typename boost::remove_reference< ThisLocation >::type >::type UnqualifiedThisLocation
ThisLocation with any const& removed.
Convenience metafunction to simplify computing the type of a particular argument to a function F...
t_< detail::if_impl< Args...>> if_
Template that will be specialized to contain callers for functors with the "this" pointer as a void *...
Struct containing a single static function member named "call" that serves as a converter from a func...
BOOST_CONSTEXPR_OR_CONST this_first_t this_first
Pass as an argument to a getCaller() overload to indicate the first parameter of the function contain...
boost::mpl::if_< boost::is_void< typename boost::function_types::result_type< FunctionPtr >::type >, boost::mpl::int_< 0 >, boost::mpl::int_< 1 > >::type Returns
Whether or not the function returns a value.
Internal metafunction to compute which caller you need based on the pointer types and this location...
GeneralResult::template Specialized< FunctionPtr, FunctionObjectType > type
Computed result.
Tag type indicating the last parameter of the function contains the "this" pointer.
boost::mpl::at< ParamTypes, boost::mpl::int_< C > >::type type
Result type.
boost::mpl::prior< boost::function_types::function_arity< FunctionPtr > >::type Arity
The function arity without the "this" parameter.
#define OSVR_MAKE_CALLERS(Z, ARITY, RETURNS)
Generates specializations of CallerThisLast and CallerThisFirst for the given values of ARITY and RET...