1 // Boost.TypeErasure library
3 // Copyright 2011 Steven Watanabe
5 // Distributed under the Boost Software License Version 1.0. (See
6 // accompanying file LICENSE_1_0.txt or copy at
7 // http://www.boost.org/LICENSE_1_0.txt)
11 #if !defined(BOOST_PP_IS_ITERATING)
13 #ifndef BOOST_TYPE_ERASURE_CALLABLE_HPP_INCLUDED
14 #define BOOST_TYPE_ERASURE_CALLABLE_HPP_INCLUDED
16 #include <boost/detail/workaround.hpp>
17 #include <boost/utility/declval.hpp>
18 #include <boost/mpl/vector.hpp>
19 #include <boost/mpl/push_back.hpp>
20 #include <boost/preprocessor/cat.hpp>
21 #include <boost/preprocessor/dec.hpp>
22 #include <boost/preprocessor/iteration/iterate.hpp>
23 #include <boost/preprocessor/repetition/enum.hpp>
24 #include <boost/preprocessor/repetition/enum_params.hpp>
25 #include <boost/preprocessor/repetition/enum_trailing_params.hpp>
26 #include <boost/preprocessor/repetition/enum_binary_params.hpp>
27 #include <boost/preprocessor/repetition/enum_trailing_binary_params.hpp>
28 #include <boost/type_erasure/config.hpp>
29 #include <boost/type_erasure/call.hpp>
30 #include <boost/type_erasure/concept_interface.hpp>
31 #include <boost/type_erasure/rebind_any.hpp>
32 #include <boost/type_erasure/param.hpp>
35 namespace type_erasure {
37 template<class Sig, class F = _self>
43 struct result_of_callable;
47 #if defined(BOOST_TYPE_ERASURE_DOXYGEN)
50 * The @ref callable concept allows an @ref any to hold function objects.
51 * @c Sig is interpreted in the same way as for Boost.Function, except
52 * that the arguments and return type are allowed to be placeholders.
53 * @c F must be a @ref placeholder.
55 * Multiple instances of @ref callable can be used
56 * simultaneously. Overload resolution works normally.
57 * Note that unlike Boost.Function, @ref callable
58 * does not provide result_type. It does, however,
59 * support @c boost::result_of.
61 template<class Sig, class F = _self>
65 * @c R is the result type of @c Sig and @c T is the argument
68 static R apply(F& f, T... arg);
71 #elif !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && \
72 !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && \
73 !BOOST_WORKAROUND(BOOST_MSVC, == 1800)
75 template<class R, class... T, class F>
76 struct callable<R(T...), F>
78 static R apply(F& f, T... arg)
80 return f(std::forward<T>(arg)...);
84 template<class... T, class F>
85 struct callable<void(T...), F>
87 static void apply(F& f, T... arg)
89 f(std::forward<T>(arg)...);
93 template<class R, class F, class Base, class Enable, class... T>
94 struct concept_interface<callable<R(T...), F>, Base, F, Enable>
99 ::boost::type_erasure::detail::result_of_callable<Sig>
101 typedef void _boost_type_erasure_is_callable;
102 typedef ::boost::mpl::vector<R> _boost_type_erasure_callable_results;
103 typedef char (&_boost_type_erasure_callable_size)[1];
104 _boost_type_erasure_callable_size
105 _boost_type_erasure_deduce_callable(
106 typename ::boost::type_erasure::as_param<Base, T>::type...);
107 typename ::boost::type_erasure::rebind_any<Base, R>::type
108 operator()(typename ::boost::type_erasure::as_param<Base, T>::type... arg)
110 return ::boost::type_erasure::call(callable<R(T...), F>(), *this,
111 ::std::forward<typename ::boost::type_erasure::as_param<Base, T>::type>(arg)...);
115 template<class R, class F, class Base, class Enable, class... T>
116 struct concept_interface<callable<R(T...), const F>, Base, F, Enable>
121 ::boost::type_erasure::detail::result_of_callable<Sig>
123 typedef void _boost_type_erasure_is_callable;
124 typedef ::boost::mpl::vector<R> _boost_type_erasure_callable_results;
125 typedef char (&_boost_type_erasure_callable_size)[1];
126 _boost_type_erasure_callable_size
127 _boost_type_erasure_deduce_callable(
128 typename ::boost::type_erasure::as_param<Base, T>::type...) const;
129 typename ::boost::type_erasure::rebind_any<Base, R>::type operator()(
130 typename ::boost::type_erasure::as_param<Base, T>::type... arg) const
132 return ::boost::type_erasure::call(callable<R(T...), const F>(), *this,
133 ::std::forward<typename ::boost::type_erasure::as_param<Base, T>::type>(arg)...);
137 template<class R, class F, class Base, class... T>
138 struct concept_interface<
139 callable<R(T...), F>,
142 typename Base::_boost_type_erasure_is_callable
146 typedef typename ::boost::mpl::push_back<
147 typename Base::_boost_type_erasure_callable_results,
149 >::type _boost_type_erasure_callable_results;
150 typedef char (&_boost_type_erasure_callable_size)[
151 ::boost::mpl::size<_boost_type_erasure_callable_results>::value];
152 using Base::_boost_type_erasure_deduce_callable;
153 _boost_type_erasure_callable_size
154 _boost_type_erasure_deduce_callable(
155 typename ::boost::type_erasure::as_param<Base, T>::type...);
156 using Base::operator();
157 typename ::boost::type_erasure::rebind_any<Base, R>::type
158 operator()(typename ::boost::type_erasure::as_param<Base, T>::type... arg)
160 return ::boost::type_erasure::call(callable<R(T...), F>(), *this,
161 ::std::forward<typename ::boost::type_erasure::as_param<Base, T>::type>(arg)...);
165 template<class R, class F, class Base, class... T>
166 struct concept_interface<
167 callable<R(T...), const F>,
170 typename Base::_boost_type_erasure_is_callable
174 typedef typename ::boost::mpl::push_back<
175 typename Base::_boost_type_erasure_callable_results,
177 >::type _boost_type_erasure_callable_results;
178 typedef char (&_boost_type_erasure_callable_size)[
179 ::boost::mpl::size<_boost_type_erasure_callable_results>::value];
180 using Base::_boost_type_erasure_deduce_callable;
181 _boost_type_erasure_callable_size
182 _boost_type_erasure_deduce_callable(
183 typename ::boost::type_erasure::as_param<Base, T>::type...) const;
184 using Base::operator();
185 typename ::boost::type_erasure::rebind_any<Base, R>::type
186 operator()(typename ::boost::type_erasure::as_param<Base, T>::type... arg) const
188 return ::boost::type_erasure::call(callable<R(T...), const F>(), *this,
189 ::std::forward<typename ::boost::type_erasure::as_param<Base, T>::type>(arg)...);
195 template<class This, class... T>
196 struct result_of_callable<This(T...)>
198 typedef typename ::boost::mpl::at_c<
199 typename This::_boost_type_erasure_callable_results,
200 sizeof(::boost::declval<This>().
201 _boost_type_erasure_deduce_callable(::boost::declval<T>()...)) - 1
210 #define BOOST_PP_FILENAME_1 <boost/type_erasure/callable.hpp>
212 #define BOOST_PP_ITERATION_LIMITS (0, BOOST_PP_DEC(BOOST_TYPE_ERASURE_MAX_ARITY))
213 #include BOOST_PP_ITERATE()
224 #define N BOOST_PP_ITERATION()
225 #define BOOST_TYPE_ERASURE_DECLVAL(z, n, data) ::boost::declval<BOOST_PP_CAT(T, n)>()
227 #define BOOST_TYPE_ERASURE_REBIND(z, n, data)\
228 typename ::boost::type_erasure::as_param<Base, BOOST_PP_CAT(T, n)>::type BOOST_PP_CAT(arg, n)
230 #ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
231 #define BOOST_TYPE_ERASURE_FORWARD(z, n, data) BOOST_PP_CAT(BOOST_PP_TUPLE_ELEM(2, 1, data), n)
232 #define BOOST_TYPE_ERASURE_FORWARD_REBIND(z, n, data) BOOST_PP_CAT(arg, n)
234 #define BOOST_TYPE_ERASURE_FORWARD(z, n, data) ::std::forward<BOOST_PP_CAT(BOOST_PP_TUPLE_ELEM(2, 0, data), n)>(BOOST_PP_CAT(BOOST_PP_TUPLE_ELEM(2, 1, data), n))
235 #define BOOST_TYPE_ERASURE_FORWARD_REBIND(z, n, data) ::std::forward<typename ::boost::type_erasure::as_param<Base, BOOST_PP_CAT(T, n)>::type>(BOOST_PP_CAT(arg, n))
238 template<class R BOOST_PP_ENUM_TRAILING_PARAMS(N, class T), class F>
239 struct callable<R(BOOST_PP_ENUM_PARAMS(N, T)), F>
241 static R apply(F& f BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(N, T, arg))
243 return f(BOOST_PP_ENUM(N, BOOST_TYPE_ERASURE_FORWARD, (T, arg)));
247 template<BOOST_PP_ENUM_PARAMS(N, class T) BOOST_PP_COMMA_IF(N) class F>
248 struct callable<void(BOOST_PP_ENUM_PARAMS(N, T)), F>
250 static void apply(F& f BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(N, T, arg))
252 f(BOOST_PP_ENUM(N, BOOST_TYPE_ERASURE_FORWARD, (T, arg)));
256 template<class R BOOST_PP_ENUM_TRAILING_PARAMS(N, class T), class F, class Base, class Enable>
257 struct concept_interface<
258 callable<R(BOOST_PP_ENUM_PARAMS(N, T)), F>,
267 ::boost::type_erasure::detail::result_of_callable<Sig>
269 typedef void _boost_type_erasure_is_callable;
270 typedef ::boost::mpl::vector<R> _boost_type_erasure_callable_results;
271 typedef char (&_boost_type_erasure_callable_size)[1];
272 _boost_type_erasure_callable_size
273 _boost_type_erasure_deduce_callable(
274 BOOST_PP_ENUM(N, BOOST_TYPE_ERASURE_REBIND, ~));
275 typename ::boost::type_erasure::rebind_any<Base, R>::type
276 operator()(BOOST_PP_ENUM(N, BOOST_TYPE_ERASURE_REBIND, ~))
278 return ::boost::type_erasure::call(
279 callable<R(BOOST_PP_ENUM_PARAMS(N, T)), F>(),
280 *this BOOST_PP_ENUM_TRAILING(N, BOOST_TYPE_ERASURE_FORWARD_REBIND, ~));
284 template<class R BOOST_PP_ENUM_TRAILING_PARAMS(N, class T), class F, class Base, class Enable>
285 struct concept_interface<
286 callable<R(BOOST_PP_ENUM_PARAMS(N, T)), const F>,
295 ::boost::type_erasure::detail::result_of_callable<Sig>
297 typedef void _boost_type_erasure_is_callable;
298 typedef ::boost::mpl::vector<R> _boost_type_erasure_callable_results;
299 typedef char (&_boost_type_erasure_callable_size)[1];
300 _boost_type_erasure_callable_size
301 _boost_type_erasure_deduce_callable(
302 BOOST_PP_ENUM(N, BOOST_TYPE_ERASURE_REBIND, ~)) const;
303 typename ::boost::type_erasure::rebind_any<Base, R>::type
304 operator()(BOOST_PP_ENUM(N, BOOST_TYPE_ERASURE_REBIND, ~)) const
306 return ::boost::type_erasure::call(
307 callable<R(BOOST_PP_ENUM_PARAMS(N, T)), const F>(),
308 *this BOOST_PP_ENUM_TRAILING(N, BOOST_TYPE_ERASURE_FORWARD_REBIND, ~));
312 template<class R BOOST_PP_ENUM_TRAILING_PARAMS(N, class T), class F, class Base>
313 struct concept_interface<
314 callable<R(BOOST_PP_ENUM_PARAMS(N, T)), F>,
317 typename Base::_boost_type_erasure_is_callable
321 typedef typename ::boost::mpl::push_back<
322 typename Base::_boost_type_erasure_callable_results,
324 >::type _boost_type_erasure_callable_results;
325 typedef char (&_boost_type_erasure_callable_size)[
326 ::boost::mpl::size<_boost_type_erasure_callable_results>::value];
327 using Base::_boost_type_erasure_deduce_callable;
328 _boost_type_erasure_callable_size
329 _boost_type_erasure_deduce_callable(
330 BOOST_PP_ENUM(N, BOOST_TYPE_ERASURE_REBIND, ~));
331 using Base::operator();
332 typename ::boost::type_erasure::rebind_any<Base, R>::type
333 operator()(BOOST_PP_ENUM(N, BOOST_TYPE_ERASURE_REBIND, ~))
335 return ::boost::type_erasure::call(
336 callable<R(BOOST_PP_ENUM_PARAMS(N, T)), F>(),
337 *this BOOST_PP_ENUM_TRAILING(N, BOOST_TYPE_ERASURE_FORWARD_REBIND, ~));
341 template<class R BOOST_PP_ENUM_TRAILING_PARAMS(N, class T), class F, class Base>
342 struct concept_interface<
343 callable<R(BOOST_PP_ENUM_PARAMS(N, T)), const F>,
346 typename Base::_boost_type_erasure_is_callable
350 typedef typename ::boost::mpl::push_back<
351 typename Base::_boost_type_erasure_callable_results,
353 >::type _boost_type_erasure_callable_results;
354 typedef char (&_boost_type_erasure_callable_size)[
355 ::boost::mpl::size<_boost_type_erasure_callable_results>::value];
356 using Base::_boost_type_erasure_deduce_callable;
357 _boost_type_erasure_callable_size
358 _boost_type_erasure_deduce_callable(
359 BOOST_PP_ENUM(N, BOOST_TYPE_ERASURE_REBIND, ~)) const;
360 using Base::operator();
361 typename ::boost::type_erasure::rebind_any<Base, R>::type
362 operator()(BOOST_PP_ENUM(N, BOOST_TYPE_ERASURE_REBIND, ~)) const
364 return ::boost::type_erasure::call(
365 callable<R(BOOST_PP_ENUM_PARAMS(N, T)), const F>(),
366 *this BOOST_PP_ENUM_TRAILING(N, BOOST_TYPE_ERASURE_FORWARD_REBIND, ~));
372 template<class This BOOST_PP_ENUM_TRAILING_PARAMS(N, class T)>
373 struct result_of_callable<This(BOOST_PP_ENUM_PARAMS(N, T))>
375 typedef typename ::boost::mpl::at_c<
376 typename This::_boost_type_erasure_callable_results,
377 sizeof(::boost::declval<This>().
378 _boost_type_erasure_deduce_callable(
379 BOOST_PP_ENUM(N, BOOST_TYPE_ERASURE_DECLVAL, ~))) - 1
385 #undef BOOST_TYPE_ERASURE_DECLVAL
386 #undef BOOST_TYPE_ERASURE_REBIND