OSVR-Core
GenericCaller.h
Go to the documentation of this file.
1 
14 // Copyright 2014 Sensics, Inc.
15 //
16 // Licensed under the Apache License, Version 2.0 (the "License");
17 // you may not use this file except in compliance with the License.
18 // You may obtain a copy of the License at
19 //
20 // http://www.apache.org/licenses/LICENSE-2.0
21 //
22 // Unless required by applicable law or agreed to in writing, software
23 // distributed under the License is distributed on an "AS IS" BASIS,
24 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
25 // See the License for the specific language governing permissions and
26 // limitations under the License.
27 
28 #ifndef INCLUDED_GenericCaller_h_GUID_C49A7DEE_89E6_478D_627A_CFFB9ED39EAC
29 #define INCLUDED_GenericCaller_h_GUID_C49A7DEE_89E6_478D_627A_CFFB9ED39EAC
30 
31 // Internal Includes
32 // - none
33 
34 // Library/third-party includes
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>
41 
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>
52 
53 #include <boost/mpl/at.hpp>
54 #include <boost/mpl/int.hpp>
55 #include <boost/mpl/next_prior.hpp>
56 
57 #include <boost/static_assert.hpp>
58 
59 // Standard includes
60 // - none
61 
62 #ifndef OSVR_UTIL_CALLER_MAX_ARITY
63 #define OSVR_UTIL_CALLER_MAX_ARITY 3
64 #endif
65 
66 namespace osvr {
67 namespace util {
68 #ifndef OSVR_DOXYGEN_EXTERNAL
69  namespace functor_trampolines {
70 #endif // ifndef OSVR_DOXYGEN_EXTERNAL
71 
76  struct this_last_t {};
81  struct this_first_t {};
82 
86  BOOST_CONSTEXPR_OR_CONST this_last_t this_last = {};
90  BOOST_CONSTEXPR_OR_CONST this_first_t this_first = {};
91 
92 #ifndef OSVR_DOXYGEN_EXTERNAL
93  namespace detail {
94 
97  template <typename F, int C> struct param_at {
98 #ifndef OSVR_DOXYGEN
99  typedef typename boost::function_types::parameter_types<F>::type
100  ParamTypes;
101 #endif
102  typedef
104  typename boost::mpl::at<ParamTypes,
105  boost::mpl::int_<C> >::type type;
106  };
107 
117  template <typename ThisLocation, int Arity, int Return>
118  struct Caller;
119 
121 #define OSVR_PARAM_STEM p
122 
125 #define OSVR_MAKE_PARAMLIST(Z, N, unused) \
126  typename param_at<FPtr, N>::type BOOST_PP_CAT(OSVR_PARAM_STEM, N)
127 
131 #define OSVR_RETURNTYPE(R) \
132  BOOST_PP_IF(R, typename boost::function_types::result_type<FPtr>::type, \
133  void)
134 
138 #define OSVR_RETURNSTATEMENT(R) BOOST_PP_IF(R, return, BOOST_PP_EMPTY())
139 
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)); \
154  } \
155  }; \
156  }; \
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)); \
165  } \
166  };
167  // Generate specializations for void returns
168  BOOST_PP_REPEAT(OSVR_UTIL_CALLER_MAX_ARITY, OSVR_MAKE_CALLERS, 0)
169  // Generate specializations for non-void returns
170  BOOST_PP_REPEAT(OSVR_UTIL_CALLER_MAX_ARITY, OSVR_MAKE_CALLERS, 1)
171 
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
187 #ifndef OSVR_DOXYGEN
188  BOOST_STATIC_ASSERT_MSG(
189  (boost::is_same<UnqualifiedThisLocation,
190  this_first_t>::value ||
191  boost::is_same<UnqualifiedThisLocation,
192  this_last_t>::value),
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 "
197  "object");
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
204 
207  typedef typename boost::mpl::prior<
208  boost::function_types::function_arity<FunctionPtr> >::type
210 
212  typedef typename boost::mpl::if_<
213  boost::is_void<typename boost::function_types::result_type<
214  FunctionPtr>::type>,
215  boost::mpl::int_<0>, boost::mpl::int_<1> >::type Returns;
216 
218  typedef detail::Caller<UnqualifiedThisLocation, Arity::value,
219  Returns::value> GeneralResult;
220 
222  typedef typename GeneralResult::template Specialized<
223  FunctionPtr, FunctionObjectType> type;
224  };
225  } // namespace detail
226 #endif // ifndef OSVR_DOXYGEN_EXTERNAL
227 
239  template <typename FunctionPtr, typename FunctionObjectType,
240  typename ThisLocation>
242  : detail::ComputeGenericCaller<FunctionPtr, FunctionObjectType,
243  ThisLocation>::type {};
244 
257  template <typename FunctionPtr, typename FunctionObjectType,
258  typename ThisLocation>
259  inline FunctionPtr getCaller() {
261  CallerType;
262  return &CallerType::call;
263  }
272  template <typename FunctionPtr, typename FunctionObjectType,
273  typename ThisLocation>
274  inline FunctionPtr
275  getCaller( ThisLocation const &) {
276  return getCaller<FunctionPtr, FunctionObjectType, ThisLocation>();
277  }
278 
292  template <typename FunctionPtr, typename FunctionObjectType,
293  typename ThisLocation>
294  inline FunctionPtr getCaller( FunctionObjectType const *, ThisLocation const &) {
297  return getCaller<FunctionPtr, FunctionObjectType, ThisLocation>();
298  }
299 #ifndef OSVR_DOXYGEN_EXTERNAL
300  } // namespace functor_trampolines
301 
302  // Import symbols into namespace.
303  using functor_trampolines::getCaller;
309 
310 #endif // ifndef OSVR_DOXYGEN_EXTERNAL
311 
312 } // namespace util
313 } // namespace osvr
314 
315 #endif // INCLUDED_GenericCaller_h_GUID_C49A7DEE_89E6_478D_627A_CFFB9ED39EAC
Definition: RunLoopManager.h:42
detail::Caller< UnqualifiedThisLocation, Arity::value, Returns::value > GeneralResult
Computed intermediate result.
Definition: GenericCaller.h:219
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...
Definition: GenericCaller.h:86
The main namespace for all C++ elements of the framework, internal and external.
Definition: namespace_osvr.dox:3
Tag type indicating the first parameter of the function contains the "this" pointer.
Definition: GenericCaller.h:81
FunctionPtr getCaller()
Get a generic functor caller: a pointer to a function that will call an object of your specific funct...
Definition: GenericCaller.h:259
boost::remove_cv< typename boost::remove_reference< ThisLocation >::type >::type UnqualifiedThisLocation
ThisLocation with any const& removed.
Definition: GenericCaller.h:186
Definition: newuoa.h:1888
Convenience metafunction to simplify computing the type of a particular argument to a function F...
Definition: GenericCaller.h:97
t_< detail::if_impl< Args... >> if_
Select one type or another depending on a compile-time Boolean integral constant type.
Definition: If.h:61
Template that will be specialized to contain callers for functors with the "this" pointer as a void *...
Definition: GenericCaller.h:118
Struct containing a single static function member named "call" that serves as a converter from a func...
Definition: GenericCaller.h:241
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...
Definition: GenericCaller.h:90
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.
Definition: GenericCaller.h:215
Internal metafunction to compute which caller you need based on the pointer types and this location...
Definition: GenericCaller.h:182
GeneralResult::template Specialized< FunctionPtr, FunctionObjectType > type
Computed result.
Definition: GenericCaller.h:223
Tag type indicating the last parameter of the function contains the "this" pointer.
Definition: GenericCaller.h:76
boost::mpl::at< ParamTypes, boost::mpl::int_< C > >::type type
Result type.
Definition: GenericCaller.h:105
boost::mpl::prior< boost::function_types::function_arity< FunctionPtr > >::type Arity
The function arity without the "this" parameter.
Definition: GenericCaller.h:209
#define OSVR_MAKE_CALLERS(Z, ARITY, RETURNS)
Generates specializations of CallerThisLast and CallerThisFirst for the given values of ARITY and RET...
Definition: GenericCaller.h:145