• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*=============================================================================
2     Copyright (c) 2007 Tobias Schwinger
3 
4     Use modification and distribution are subject to the Boost Software
5     License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
6     http://www.boost.org/LICENSE_1_0.txt).
7 ==============================================================================*/
8 
9 #ifndef BOOST_FUNCTIONAL_LIGHTWEIGHT_FORWARD_ADAPTER_HPP_INCLUDED
10 #   ifndef BOOST_PP_IS_ITERATING
11 
12 #   include <boost/config.hpp>
13 #   include <boost/config/workaround.hpp>
14 
15 #   include <boost/preprocessor/cat.hpp>
16 #   include <boost/preprocessor/iteration/iterate.hpp>
17 #   include <boost/preprocessor/repetition/enum.hpp>
18 #   include <boost/preprocessor/repetition/enum_params.hpp>
19 #   include <boost/preprocessor/repetition/enum_binary_params.hpp>
20 #   include <boost/preprocessor/facilities/intercept.hpp>
21 
22 #   include <boost/utility/result_of.hpp>
23 #   include <boost/ref.hpp>
24 
25 #   ifndef BOOST_FUNCTIONAL_LIGHTWEIGHT_FORWARD_ADAPTER_MAX_ARITY
26 #     define BOOST_FUNCTIONAL_LIGHTWEIGHT_FORWARD_ADAPTER_MAX_ARITY 10
27 #   elif BOOST_FUNCTIONAL_FORDWARD_ADAPTER_MAX_ARITY < 3
28 #     undef  BOOST_FUNCTIONAL_LIGHTWEIGHT_FORWARD_ADAPTER_MAX_ARITY
29 #     define BOOST_FUNCTIONAL_LIGHTWEIGHT_FORWARD_ADAPTER_MAX_ARITY 3
30 #   endif
31 
32 namespace boost
33 {
34     template< typename Function, int Arity_Or_MinArity = -1, int MaxArity = -1 >
35     class lightweight_forward_adapter;
36 
37     //----- ---- --- -- - -  -   -
38 
39     namespace detail
40     {
41         template< class MostDerived, typename Function, typename FunctionConst,
42             int Arity, int MinArity >
43         struct lightweight_forward_adapter_impl;
44 
45         struct lightweight_forward_adapter_result
46         {
47             template< typename Sig > struct apply;
48 
49             // Utility metafunction for argument transform
50             template< typename T > struct x  { typedef T const& t; };
51             template< typename T > struct x< boost::reference_wrapper<T> >
52             { typedef T& t; };
53             template< typename T > struct x<T&>       : x<T> { };
54             template< typename T > struct x<T const&> : x<T> { };
55             template< typename T > struct x<T const>  : x<T> { };
56 
57             // Utility metafunction to choose target function qualification
58             template< typename T > struct c
59             { typedef typename T::target_function_t t; };
60             template< typename T > struct c<T&      >
61             { typedef typename T::target_function_t t; };
62             template< typename T > struct c<T const >
63             { typedef typename T::target_function_const_t t; };
64             template< typename T > struct c<T const&>
65             { typedef typename T::target_function_const_t t; };
66         };
67     }
68 
69 #   define BOOST_TMP_MACRO(f,fn,fc) \
70         boost::detail::lightweight_forward_adapter_impl< \
71             lightweight_forward_adapter<f,Arity_Or_MinArity,MaxArity>, fn, fc, \
72             (MaxArity!=-1? MaxArity :Arity_Or_MinArity!=-1? Arity_Or_MinArity \
73                 :BOOST_FUNCTIONAL_LIGHTWEIGHT_FORWARD_ADAPTER_MAX_ARITY), \
74             (Arity_Or_MinArity!=-1? Arity_Or_MinArity : 0) >
75 
76     template< typename Function, int Arity_Or_MinArity, int MaxArity >
77     class lightweight_forward_adapter
78         : public BOOST_TMP_MACRO(Function,Function,Function const)
79         , private Function
80     {
81       public:
lightweight_forward_adapter(Function const & f=Function ())82         lightweight_forward_adapter(Function const& f = Function())
83           : Function(f)
84         { }
85 
86         typedef Function        target_function_t;
87         typedef Function const  target_function_const_t;
88 
target_function()89         Function       & target_function()       { return *this; }
target_function() const90         Function const & target_function() const { return *this; }
91 
92         template< typename Sig > struct result
93             : detail::lightweight_forward_adapter_result::template apply<Sig>
94         { };
95 
96         using BOOST_TMP_MACRO(Function,Function, Function const)::operator();
97     };
98     template< typename Function, int Arity_Or_MinArity, int MaxArity >
99     class lightweight_forward_adapter< Function const, Arity_Or_MinArity,
100         MaxArity >
101         : public BOOST_TMP_MACRO(Function const, Function const, Function const)
102         , private Function
103     {
104       public:
lightweight_forward_adapter(Function const & f=Function ())105         lightweight_forward_adapter(Function const& f = Function())
106           : Function(f)
107         { }
108 
109         typedef Function const target_function_t;
110         typedef Function const target_function_const_t;
111 
target_function() const112         Function const & target_function() const { return *this; }
113 
114         template< typename Sig > struct result
115             : detail::lightweight_forward_adapter_result::template apply<Sig>
116         { };
117 
118         using BOOST_TMP_MACRO(Function const,Function const, Function const)
119             ::operator();
120     };
121     template< typename Function, int Arity_Or_MinArity, int MaxArity >
122     class lightweight_forward_adapter< Function &, Arity_Or_MinArity, MaxArity >
123         : public BOOST_TMP_MACRO(Function&, Function, Function)
124     {
125         Function& ref_function;
126       public:
lightweight_forward_adapter(Function & f)127         lightweight_forward_adapter(Function& f)
128           : ref_function(f)
129         { }
130 
131         typedef Function target_function_t;
132         typedef Function target_function_const_t;
133 
target_function() const134         Function & target_function() const { return this->ref_function; }
135 
136         template< typename Sig > struct result
137             : detail::lightweight_forward_adapter_result::template apply<Sig>
138         { };
139 
140         using BOOST_TMP_MACRO(Function&, Function, Function)::operator();
141     };
142 
143     #undef BOOST_TMP_MACRO
144 
145     namespace detail
146     {
147         template< class Self >
148         struct lightweight_forward_adapter_result::apply< Self() >
149             : boost::result_of< BOOST_DEDUCED_TYPENAME c<Self>::t() >
150         { };
151 
152         // When operator() doesn't have any parameters, it can't
153         // be templatized and can't use SFINAE, so intead use class
154         // template parameter SFINAE to decide whether to instantiate it.
155 
156         template <typename T, typename R = void>
157         struct lightweight_forward_adapter_sfinae
158         {
159             typedef T type;
160         };
161 
162         // This is the fallback for when there isn't an operator()(),
163         // need to create an operator() that will never instantiate
164         // so that using parent::operator() will work okay.
165         template< class MD, class F, class FC, class Enable = void>
166         struct lightweight_forward_adapter_impl_zero
167             : lightweight_forward_adapter_result
168         {
169             template <typename T> struct never_instantiate {};
170             template <typename T>
operator ()boost::detail::lightweight_forward_adapter_impl_zero171             typename never_instantiate<T>::type operator()(T) const {}
172         };
173 
174         template< class MD, class F, class FC>
175         struct lightweight_forward_adapter_impl_zero<MD, F, FC,
176             typename lightweight_forward_adapter_sfinae<typename boost::result_of< FC() >::type>::type>
177             : lightweight_forward_adapter_result
178         {
179             inline typename boost::result_of< FC() >::type
operator ()boost::detail::lightweight_forward_adapter_impl_zero180             operator()() const
181             {
182                 return static_cast<MD const*>(this)->target_function()();
183             }
184 
185             inline typename boost::result_of< F() >::type
operator ()boost::detail::lightweight_forward_adapter_impl_zero186             operator()()
187             {
188                 return static_cast<MD*>(this)->target_function()();
189             }
190         };
191 
192         template< class MD, class F, class FC >
193         struct lightweight_forward_adapter_impl<MD,F,FC,0,0>
194             : lightweight_forward_adapter_impl_zero<MD,F,FC>
195         {
196         };
197 
198 #       define  BOOST_PP_FILENAME_1 \
199             <boost/functional/lightweight_forward_adapter.hpp>
200 #       define  BOOST_PP_ITERATION_LIMITS                                     \
201             (1,BOOST_FUNCTIONAL_LIGHTWEIGHT_FORWARD_ADAPTER_MAX_ARITY)
202 #       include BOOST_PP_ITERATE()
203 
204     } // namespace detail
205 
206     template<class F, int A0, int A1>
207     struct result_of<boost::lightweight_forward_adapter<F,A0,A1> const ()>
208         : boost::detail::lightweight_forward_adapter_result::template apply<
209             boost::lightweight_forward_adapter<F,A0,A1> const () >
210     { };
211     template<class F, int A0, int A1>
212     struct result_of<boost::lightweight_forward_adapter<F,A0,A1>()>
213         : boost::detail::lightweight_forward_adapter_result::template apply<
214             boost::lightweight_forward_adapter<F,A0,A1>() >
215     { };
216     template<class F, int A0, int A1>
217     struct result_of<boost::lightweight_forward_adapter<F,A0,A1> const& ()>
218         : boost::detail::lightweight_forward_adapter_result::template apply<
219             boost::lightweight_forward_adapter<F,A0,A1> const () >
220     { };
221     template<class F, int A0, int A1>
222     struct result_of<boost::lightweight_forward_adapter<F,A0,A1>& ()>
223         : boost::detail::lightweight_forward_adapter_result::template apply<
224             boost::lightweight_forward_adapter<F,A0,A1>() >
225     { };
226 }
227 
228 #     define BOOST_FUNCTIONAL_LIGHTWEIGHT_FORWARD_ADAPTER_HPP_INCLUDED
229 
230 #   else // defined(BOOST_PP_IS_ITERATING)
231 #     define N BOOST_PP_ITERATION()
232 
233         template< class Self, BOOST_PP_ENUM_PARAMS(N,typename T) >
234         struct lightweight_forward_adapter_result::apply<
235             Self (BOOST_PP_ENUM_PARAMS(N,T)) >
236             : boost::result_of<
237                 BOOST_DEDUCED_TYPENAME c<Self>::t (BOOST_PP_ENUM_BINARY_PARAMS(N,
238                     typename x<T,>::t BOOST_PP_INTERCEPT)) >
239         { };
240 
241         template< class MD, class F, class FC >
242         struct lightweight_forward_adapter_impl<MD,F,FC,BOOST_PP_DEC(N),N>
243             : lightweight_forward_adapter_result
244         {
245             template< BOOST_PP_ENUM_PARAMS(N,typename T) >
246             inline typename boost::result_of< F(BOOST_PP_ENUM_BINARY_PARAMS(N,
247                 T,const& BOOST_PP_INTERCEPT)) >::type
248             operator()(BOOST_PP_ENUM_BINARY_PARAMS(N,T,& BOOST_PP_INTERCEPT));
249         };
250 
251         template< class MD, class F, class FC, int MinArity >
252         struct lightweight_forward_adapter_impl<MD,F,FC,N,MinArity>
253             : lightweight_forward_adapter_impl<MD,F,FC,BOOST_PP_DEC(N),MinArity>
254         {
255             using lightweight_forward_adapter_impl<MD,F,FC,BOOST_PP_DEC(N),
256                 MinArity>::operator();
257 
258 #     define M(z,i,d) \
259           static_cast<typename d::template x<T##i>::t>(a##i)
260 
261             template< BOOST_PP_ENUM_PARAMS(N,typename T) >
262             inline typename lightweight_forward_adapter_result::template apply<
263                 MD const (BOOST_PP_ENUM_BINARY_PARAMS(N,
264                     T,const& BOOST_PP_INTERCEPT)) >::type
operator ()lightweight_forward_adapter_impl265             operator()(BOOST_PP_ENUM_BINARY_PARAMS(N,T,const& a)) const
266             {
267                 typedef lightweight_forward_adapter_result _;
268                 return static_cast<MD const*>(this)->target_function()(
269                     BOOST_PP_ENUM(N,M,_));
270             }
271             template< BOOST_PP_ENUM_PARAMS(N,typename T) >
272             inline typename lightweight_forward_adapter_result::template apply<
273                 MD (BOOST_PP_ENUM_BINARY_PARAMS(N,
274                     T,const& BOOST_PP_INTERCEPT)) >::type
operator ()lightweight_forward_adapter_impl275             operator()(BOOST_PP_ENUM_BINARY_PARAMS(N,T,const& a))
276             {
277                 typedef lightweight_forward_adapter_result _;
278                 return static_cast<MD*>(this)->target_function()(
279                     BOOST_PP_ENUM(N,M,_));
280             }
281 #     undef M
282       };
283 
284 #     undef N
285 #   endif // defined(BOOST_PP_IS_ITERATING)
286 
287 #endif // include guard
288 
289