Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:39:09

0001 // Boost Lambda Library  ret.hpp -----------------------------------------
0002 
0003 // Copyright (C) 1999, 2000 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi)
0004 //
0005 // Distributed under the Boost Software License, Version 1.0. (See
0006 // accompanying file LICENSE_1_0.txt or copy at
0007 // http://www.boost.org/LICENSE_1_0.txt)
0008 //
0009 // For more information, see www.boost.org
0010 
0011 
0012 #ifndef BOOST_LAMBDA_RET_HPP
0013 #define BOOST_LAMBDA_RET_HPP
0014 
0015 namespace boost { 
0016 namespace lambda {
0017 
0018   // TODO:
0019 
0020 //  Add specializations for function references for ret, protect and unlambda
0021 //  e.g void foo(); unlambda(foo); fails, as it would add a const qualifier
0022   // for a function type. 
0023   // on the other hand unlambda(*foo) does work
0024 
0025 
0026 // -- ret -------------------------
0027 // the explicit return type template 
0028 
0029   // TODO: It'd be nice to make ret a nop for other than lambda functors
0030   // but causes an ambiguiyty with gcc (not with KCC), check what is the
0031   // right interpretation.
0032 
0033   //  // ret for others than lambda functors has no effect
0034   // template <class U, class T>
0035   // inline const T& ret(const T& t) { return t; }
0036 
0037 
0038 template<class RET, class Arg>
0039 inline const 
0040 lambda_functor<
0041   lambda_functor_base<
0042     explicit_return_type_action<RET>, 
0043     tuple<lambda_functor<Arg> >
0044   > 
0045 >
0046 ret(const lambda_functor<Arg>& a1)
0047 {
0048   return  
0049     lambda_functor_base<
0050       explicit_return_type_action<RET>, 
0051       tuple<lambda_functor<Arg> >
0052     > 
0053     (tuple<lambda_functor<Arg> >(a1));
0054 }
0055 
0056 // protect ------------------
0057 
0058   // protecting others than lambda functors has no effect
0059 template <class T>
0060 inline const T& protect(const T& t) { return t; }
0061 
0062 template<class Arg>
0063 inline const 
0064 lambda_functor<
0065   lambda_functor_base<
0066     protect_action, 
0067     tuple<lambda_functor<Arg> >
0068   > 
0069 >
0070 protect(const lambda_functor<Arg>& a1)
0071 {
0072   return 
0073       lambda_functor_base<
0074         protect_action, 
0075         tuple<lambda_functor<Arg> >
0076       > 
0077     (tuple<lambda_functor<Arg> >(a1));
0078 }
0079    
0080 // -------------------------------------------------------------------
0081 
0082 // Hides the lambda functorness of a lambda functor. 
0083 // After this, the functor is immune to argument substitution, etc.
0084 // This can be used, e.g. to make it safe to pass lambda functors as 
0085 // arguments to functions, which might use them as target functions
0086 
0087 // note, unlambda and protect are different things. Protect hides the lambda
0088 // functor for one application, unlambda for good.
0089 
0090 template <class LambdaFunctor>
0091 class non_lambda_functor
0092 {
0093   LambdaFunctor lf;
0094 public:
0095   
0096   // This functor defines the result_type typedef.
0097   // The result type must be deducible without knowing the arguments
0098 
0099   template <class SigArgs> struct sig {
0100     typedef typename 
0101       LambdaFunctor::inherited:: 
0102         template sig<typename SigArgs::tail_type>::type type;
0103   };
0104 
0105   explicit non_lambda_functor(const LambdaFunctor& a) : lf(a) {}
0106 
0107   typename LambdaFunctor::nullary_return_type  
0108   operator()() const {
0109     return lf.template 
0110       call<typename LambdaFunctor::nullary_return_type>
0111         (cnull_type(), cnull_type(), cnull_type(), cnull_type()); 
0112   }
0113 
0114   template<class A>
0115   typename sig<tuple<const non_lambda_functor, A&> >::type 
0116   operator()(A& a) const {
0117     return lf.template call<typename sig<tuple<const non_lambda_functor, A&> >::type >(a, cnull_type(), cnull_type(), cnull_type()); 
0118   }
0119 
0120   template<class A, class B>
0121   typename sig<tuple<const non_lambda_functor, A&, B&> >::type 
0122   operator()(A& a, B& b) const {
0123     return lf.template call<typename sig<tuple<const non_lambda_functor, A&, B&> >::type >(a, b, cnull_type(), cnull_type()); 
0124   }
0125 
0126   template<class A, class B, class C>
0127   typename sig<tuple<const non_lambda_functor, A&, B&, C&> >::type 
0128   operator()(A& a, B& b, C& c) const {
0129     return lf.template call<typename sig<tuple<const non_lambda_functor, A&, B&, C&> >::type>(a, b, c, cnull_type()); 
0130   }
0131 };
0132 
0133 template <class Arg>
0134 inline const Arg& unlambda(const Arg& a) { return a; }
0135 
0136 template <class Arg>
0137 inline const non_lambda_functor<lambda_functor<Arg> > 
0138 unlambda(const lambda_functor<Arg>& a)
0139 {
0140   return non_lambda_functor<lambda_functor<Arg> >(a);
0141 }
0142 
0143   // Due to a language restriction, lambda functors cannot be made to
0144   // accept non-const rvalue arguments. Usually iterators do not return 
0145   // temporaries, but sometimes they do. That's why a workaround is provided.
0146   // Note, that this potentially breaks const correctness, so be careful!
0147 
0148 // any lambda functor can be turned into a const_incorrect_lambda_functor
0149 // The operator() takes arguments as consts and then casts constness
0150 // away. So this breaks const correctness!!! but is a necessary workaround
0151 // in some cases due to language limitations.
0152 // Note, that this is not a lambda_functor anymore, so it can not be used
0153 // as a sub lambda expression.
0154 
0155 template <class LambdaFunctor>
0156 struct const_incorrect_lambda_functor {
0157   LambdaFunctor lf;
0158 public:
0159 
0160   explicit const_incorrect_lambda_functor(const LambdaFunctor& a) : lf(a) {}
0161 
0162   template <class SigArgs> struct sig {
0163     typedef typename
0164       LambdaFunctor::inherited::template 
0165         sig<typename SigArgs::tail_type>::type type;
0166   };
0167 
0168   // The nullary case is not needed (no arguments, no parameter type problems)
0169 
0170   template<class A>
0171   typename sig<tuple<const const_incorrect_lambda_functor, A&> >::type
0172   operator()(const A& a) const {
0173     return lf.template call<typename sig<tuple<const const_incorrect_lambda_functor, A&> >::type >(const_cast<A&>(a), cnull_type(), cnull_type(), cnull_type());
0174   }
0175 
0176   template<class A, class B>
0177   typename sig<tuple<const const_incorrect_lambda_functor, A&, B&> >::type
0178   operator()(const A& a, const B& b) const {
0179     return lf.template call<typename sig<tuple<const const_incorrect_lambda_functor, A&, B&> >::type >(const_cast<A&>(a), const_cast<B&>(b), cnull_type(), cnull_type());
0180   }
0181 
0182   template<class A, class B, class C>
0183   typename sig<tuple<const const_incorrect_lambda_functor, A&, B&, C&> >::type
0184   operator()(const A& a, const B& b, const C& c) const {
0185     return lf.template call<typename sig<tuple<const const_incorrect_lambda_functor, A&, B&, C&> >::type>(const_cast<A&>(a), const_cast<B&>(b), const_cast<C&>(c), cnull_type());
0186   }
0187 };
0188 
0189 // ------------------------------------------------------------------------
0190 // any lambda functor can be turned into a const_parameter_lambda_functor
0191 // The operator() takes arguments as const.
0192 // This is useful if lambda functors are called with non-const rvalues.
0193 // Note, that this is not a lambda_functor anymore, so it can not be used
0194 // as a sub lambda expression.
0195 
0196 template <class LambdaFunctor>
0197 struct const_parameter_lambda_functor {
0198   LambdaFunctor lf;
0199 public:
0200 
0201   explicit const_parameter_lambda_functor(const LambdaFunctor& a) : lf(a) {}
0202 
0203   template <class SigArgs> struct sig {
0204     typedef typename
0205       LambdaFunctor::inherited::template 
0206         sig<typename SigArgs::tail_type>::type type;
0207   };
0208 
0209   // The nullary case is not needed: no arguments, no constness problems.
0210 
0211   template<class A>
0212   typename sig<tuple<const const_parameter_lambda_functor, const A&> >::type
0213   operator()(const A& a) const {
0214     return lf.template call<typename sig<tuple<const const_parameter_lambda_functor, const A&> >::type >(a, cnull_type(), cnull_type(), cnull_type());
0215   }
0216 
0217   template<class A, class B>
0218   typename sig<tuple<const const_parameter_lambda_functor, const A&, const B&> >::type
0219   operator()(const A& a, const B& b) const {
0220     return lf.template call<typename sig<tuple<const const_parameter_lambda_functor, const A&, const B&> >::type >(a, b, cnull_type(), cnull_type());
0221   }
0222 
0223   template<class A, class B, class C>
0224   typename sig<tuple<const const_parameter_lambda_functor, const A&, const B&, const C&>
0225 >::type
0226   operator()(const A& a, const B& b, const C& c) const {
0227     return lf.template call<typename sig<tuple<const const_parameter_lambda_functor, const A&, const B&, const C&> >::type>(a, b, c, cnull_type());
0228   }
0229 };
0230 
0231 template <class Arg>
0232 inline const const_incorrect_lambda_functor<lambda_functor<Arg> >
0233 break_const(const lambda_functor<Arg>& lf)
0234 {
0235   return const_incorrect_lambda_functor<lambda_functor<Arg> >(lf);
0236 }
0237 
0238 
0239 template <class Arg>
0240 inline const const_parameter_lambda_functor<lambda_functor<Arg> >
0241 const_parameters(const lambda_functor<Arg>& lf)
0242 {
0243   return const_parameter_lambda_functor<lambda_functor<Arg> >(lf);
0244 }
0245 
0246 // make void ------------------------------------------------
0247 // make_void( x ) turns a lambda functor x with some return type y into
0248 // another lambda functor, which has a void return type
0249 // when called, the original return type is discarded
0250 
0251 // we use this action. The action class will be called, which means that
0252 // the wrapped lambda functor is evaluated, but we just don't do anything
0253 // with the result.
0254 struct voidifier_action {
0255   template<class Ret, class A> static void apply(A&) {}
0256 };
0257 
0258 template<class Args> struct return_type_N<voidifier_action, Args> {
0259   typedef void type;
0260 };
0261 
0262 template<class Arg1>
0263 inline const 
0264 lambda_functor<
0265   lambda_functor_base<
0266     action<1, voidifier_action>,
0267     tuple<lambda_functor<Arg1> >
0268   > 
0269 > 
0270 make_void(const lambda_functor<Arg1>& a1) { 
0271 return 
0272     lambda_functor_base<
0273       action<1, voidifier_action>,
0274       tuple<lambda_functor<Arg1> >
0275     > 
0276   (tuple<lambda_functor<Arg1> > (a1));
0277 }
0278 
0279 // for non-lambda functors, make_void does nothing 
0280 // (the argument gets evaluated immediately)
0281 
0282 template<class Arg1>
0283 inline const 
0284 lambda_functor<
0285   lambda_functor_base<do_nothing_action, null_type> 
0286 > 
0287 make_void(const Arg1&) { 
0288 return 
0289     lambda_functor_base<do_nothing_action, null_type>();
0290 }
0291 
0292 // std_functor -----------------------------------------------------
0293 
0294 //  The STL uses the result_type typedef as the convention to let binders know
0295 //  the return type of a function object. 
0296 //  LL uses the sig template.
0297 //  To let LL know that the function object has the result_type typedef 
0298 //  defined, it can be wrapped with the std_functor function.
0299 
0300 
0301 // Just inherit form the template parameter (the standard functor), 
0302 // and provide a sig template. So we have a class which is still the
0303 // same functor + the sig template.
0304 
0305 template<class T>
0306 struct result_type_to_sig : public T {
0307   template<class Args> struct sig { typedef typename T::result_type type; };
0308   result_type_to_sig(const T& t) : T(t) {}
0309 };
0310 
0311 template<class F>
0312 inline result_type_to_sig<F> std_functor(const F& f) { return f; }
0313 
0314 
0315 } // namespace lambda 
0316 } // namespace boost
0317 
0318 #endif
0319 
0320 
0321 
0322 
0323 
0324 
0325