epoc32/include/stdapis/boost/lambda/detail/ret.hpp
branchSymbian2
changeset 2 2fe1408b6811
equal deleted inserted replaced
1:666f914201fb 2:2fe1408b6811
       
     1 // Boost Lambda Library  ret.hpp -----------------------------------------
       
     2 
       
     3 // Copyright (C) 1999, 2000 Jaakko Järvi (jaakko.jarvi@cs.utu.fi)
       
     4 //
       
     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)
       
     8 //
       
     9 // For more information, see www.boost.org
       
    10 
       
    11 
       
    12 #ifndef BOOST_LAMBDA_RET_HPP
       
    13 #define BOOST_LAMBDA_RET_HPP
       
    14 
       
    15 namespace boost { 
       
    16 namespace lambda {
       
    17 
       
    18   // TODO:
       
    19 
       
    20 //  Add specializations for function references for ret, protect and unlambda
       
    21 //  e.g void foo(); unlambda(foo); fails, as it would add a const qualifier
       
    22   // for a function type. 
       
    23   // on the other hand unlambda(*foo) does work
       
    24 
       
    25 
       
    26 // -- ret -------------------------
       
    27 // the explicit return type template 
       
    28 
       
    29   // TODO: It'd be nice to make ret a nop for other than lambda functors
       
    30   // but causes an ambiguiyty with gcc (not with KCC), check what is the
       
    31   // right interpretation.
       
    32 
       
    33   //  // ret for others than lambda functors has no effect
       
    34   // template <class U, class T>
       
    35   // inline const T& ret(const T& t) { return t; }
       
    36 
       
    37 
       
    38 template<class RET, class Arg>
       
    39 inline const 
       
    40 lambda_functor<
       
    41   lambda_functor_base<
       
    42     explicit_return_type_action<RET>, 
       
    43     tuple<lambda_functor<Arg> >
       
    44   > 
       
    45 >
       
    46 ret(const lambda_functor<Arg>& a1)
       
    47 {
       
    48   return  
       
    49     lambda_functor_base<
       
    50       explicit_return_type_action<RET>, 
       
    51       tuple<lambda_functor<Arg> >
       
    52     > 
       
    53     (tuple<lambda_functor<Arg> >(a1));
       
    54 }
       
    55 
       
    56 // protect ------------------
       
    57 
       
    58   // protecting others than lambda functors has no effect
       
    59 template <class T>
       
    60 inline const T& protect(const T& t) { return t; }
       
    61 
       
    62 template<class Arg>
       
    63 inline const 
       
    64 lambda_functor<
       
    65   lambda_functor_base<
       
    66     protect_action, 
       
    67     tuple<lambda_functor<Arg> >
       
    68   > 
       
    69 >
       
    70 protect(const lambda_functor<Arg>& a1)
       
    71 {
       
    72   return 
       
    73       lambda_functor_base<
       
    74         protect_action, 
       
    75         tuple<lambda_functor<Arg> >
       
    76       > 
       
    77     (tuple<lambda_functor<Arg> >(a1));
       
    78 }
       
    79    
       
    80 // -------------------------------------------------------------------
       
    81 
       
    82 // Hides the lambda functorness of a lambda functor. 
       
    83 // After this, the functor is immune to argument substitution, etc.
       
    84 // This can be used, e.g. to make it safe to pass lambda functors as 
       
    85 // arguments to functions, which might use them as target functions
       
    86 
       
    87 // note, unlambda and protect are different things. Protect hides the lambda
       
    88 // functor for one application, unlambda for good.
       
    89 
       
    90 template <class LambdaFunctor>
       
    91 class non_lambda_functor
       
    92 {
       
    93   LambdaFunctor lf;
       
    94 public:
       
    95   
       
    96   // This functor defines the result_type typedef.
       
    97   // The result type must be deducible without knowing the arguments
       
    98 
       
    99   template <class SigArgs> struct sig {
       
   100     typedef typename 
       
   101       LambdaFunctor::inherited:: 
       
   102         template sig<typename SigArgs::tail_type>::type type;
       
   103   };
       
   104 
       
   105   explicit non_lambda_functor(const LambdaFunctor& a) : lf(a) {}
       
   106 
       
   107   typename LambdaFunctor::nullary_return_type  
       
   108   operator()() const {
       
   109     return lf.template 
       
   110       call<typename LambdaFunctor::nullary_return_type>
       
   111         (cnull_type(), cnull_type(), cnull_type(), cnull_type()); 
       
   112   }
       
   113 
       
   114   template<class A>
       
   115   typename sig<tuple<const non_lambda_functor, A&> >::type 
       
   116   operator()(A& a) const {
       
   117     return lf.template call<typename sig<tuple<const non_lambda_functor, A&> >::type >(a, cnull_type(), cnull_type(), cnull_type()); 
       
   118   }
       
   119 
       
   120   template<class A, class B>
       
   121   typename sig<tuple<const non_lambda_functor, A&, B&> >::type 
       
   122   operator()(A& a, B& b) const {
       
   123     return lf.template call<typename sig<tuple<const non_lambda_functor, A&, B&> >::type >(a, b, cnull_type(), cnull_type()); 
       
   124   }
       
   125 
       
   126   template<class A, class B, class C>
       
   127   typename sig<tuple<const non_lambda_functor, A&, B&, C&> >::type 
       
   128   operator()(A& a, B& b, C& c) const {
       
   129     return lf.template call<typename sig<tuple<const non_lambda_functor, A&, B&, C&> >::type>(a, b, c, cnull_type()); 
       
   130   }
       
   131 };
       
   132 
       
   133 template <class Arg>
       
   134 inline const Arg& unlambda(const Arg& a) { return a; }
       
   135 
       
   136 template <class Arg>
       
   137 inline const non_lambda_functor<lambda_functor<Arg> > 
       
   138 unlambda(const lambda_functor<Arg>& a)
       
   139 {
       
   140   return non_lambda_functor<lambda_functor<Arg> >(a);
       
   141 }
       
   142 
       
   143   // Due to a language restriction, lambda functors cannot be made to
       
   144   // accept non-const rvalue arguments. Usually iterators do not return 
       
   145   // temporaries, but sometimes they do. That's why a workaround is provided.
       
   146   // Note, that this potentially breaks const correctness, so be careful!
       
   147 
       
   148 // any lambda functor can be turned into a const_incorrect_lambda_functor
       
   149 // The operator() takes arguments as consts and then casts constness
       
   150 // away. So this breaks const correctness!!! but is a necessary workaround
       
   151 // in some cases due to language limitations.
       
   152 // Note, that this is not a lambda_functor anymore, so it can not be used
       
   153 // as a sub lambda expression.
       
   154 
       
   155 template <class LambdaFunctor>
       
   156 struct const_incorrect_lambda_functor {
       
   157   LambdaFunctor lf;
       
   158 public:
       
   159 
       
   160   explicit const_incorrect_lambda_functor(const LambdaFunctor& a) : lf(a) {}
       
   161 
       
   162   template <class SigArgs> struct sig {
       
   163     typedef typename
       
   164       LambdaFunctor::inherited::template 
       
   165         sig<typename SigArgs::tail_type>::type type;
       
   166   };
       
   167 
       
   168   // The nullary case is not needed (no arguments, no parameter type problems)
       
   169 
       
   170   template<class A>
       
   171   typename sig<tuple<const const_incorrect_lambda_functor, A&> >::type
       
   172   operator()(const A& a) const {
       
   173     return lf.template call<typename sig<tuple<const const_incorrect_lambda_functor, A&> >::type >(const_cast<A&>(a), cnull_type(), cnull_type(), cnull_type());
       
   174   }
       
   175 
       
   176   template<class A, class B>
       
   177   typename sig<tuple<const const_incorrect_lambda_functor, A&, B&> >::type
       
   178   operator()(const A& a, const B& b) const {
       
   179     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());
       
   180   }
       
   181 
       
   182   template<class A, class B, class C>
       
   183   typename sig<tuple<const const_incorrect_lambda_functor, A&, B&, C&> >::type
       
   184   operator()(const A& a, const B& b, const C& c) const {
       
   185     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());
       
   186   }
       
   187 };
       
   188 
       
   189 // ------------------------------------------------------------------------
       
   190 // any lambda functor can be turned into a const_parameter_lambda_functor
       
   191 // The operator() takes arguments as const.
       
   192 // This is useful if lambda functors are called with non-const rvalues.
       
   193 // Note, that this is not a lambda_functor anymore, so it can not be used
       
   194 // as a sub lambda expression.
       
   195 
       
   196 template <class LambdaFunctor>
       
   197 struct const_parameter_lambda_functor {
       
   198   LambdaFunctor lf;
       
   199 public:
       
   200 
       
   201   explicit const_parameter_lambda_functor(const LambdaFunctor& a) : lf(a) {}
       
   202 
       
   203   template <class SigArgs> struct sig {
       
   204     typedef typename
       
   205       LambdaFunctor::inherited::template 
       
   206         sig<typename SigArgs::tail_type>::type type;
       
   207   };
       
   208 
       
   209   // The nullary case is not needed: no arguments, no constness problems.
       
   210 
       
   211   template<class A>
       
   212   typename sig<tuple<const const_parameter_lambda_functor, const A&> >::type
       
   213   operator()(const A& a) const {
       
   214     return lf.template call<typename sig<tuple<const const_parameter_lambda_functor, const A&> >::type >(a, cnull_type(), cnull_type(), cnull_type());
       
   215   }
       
   216 
       
   217   template<class A, class B>
       
   218   typename sig<tuple<const const_parameter_lambda_functor, const A&, const B&> >::type
       
   219   operator()(const A& a, const B& b) const {
       
   220     return lf.template call<typename sig<tuple<const const_parameter_lambda_functor, const A&, const B&> >::type >(a, b, cnull_type(), cnull_type());
       
   221   }
       
   222 
       
   223   template<class A, class B, class C>
       
   224   typename sig<tuple<const const_parameter_lambda_functor, const A&, const B&, const C&>
       
   225 >::type
       
   226   operator()(const A& a, const B& b, const C& c) const {
       
   227     return lf.template call<typename sig<tuple<const const_parameter_lambda_functor, const A&, const B&, const C&> >::type>(a, b, c, cnull_type());
       
   228   }
       
   229 };
       
   230 
       
   231 template <class Arg>
       
   232 inline const const_incorrect_lambda_functor<lambda_functor<Arg> >
       
   233 break_const(const lambda_functor<Arg>& lf)
       
   234 {
       
   235   return const_incorrect_lambda_functor<lambda_functor<Arg> >(lf);
       
   236 }
       
   237 
       
   238 
       
   239 template <class Arg>
       
   240 inline const const_parameter_lambda_functor<lambda_functor<Arg> >
       
   241 const_parameters(const lambda_functor<Arg>& lf)
       
   242 {
       
   243   return const_parameter_lambda_functor<lambda_functor<Arg> >(lf);
       
   244 }
       
   245 
       
   246 // make void ------------------------------------------------
       
   247 // make_void( x ) turns a lambda functor x with some return type y into
       
   248 // another lambda functor, which has a void return type
       
   249 // when called, the original return type is discarded
       
   250 
       
   251 // we use this action. The action class will be called, which means that
       
   252 // the wrapped lambda functor is evaluated, but we just don't do anything
       
   253 // with the result.
       
   254 struct voidifier_action {
       
   255   template<class Ret, class A> static void apply(A&) {}
       
   256 };
       
   257 
       
   258 template<class Args> struct return_type_N<voidifier_action, Args> {
       
   259   typedef void type;
       
   260 };
       
   261 
       
   262 template<class Arg1>
       
   263 inline const 
       
   264 lambda_functor<
       
   265   lambda_functor_base<
       
   266     action<1, voidifier_action>,
       
   267     tuple<lambda_functor<Arg1> >
       
   268   > 
       
   269 > 
       
   270 make_void(const lambda_functor<Arg1>& a1) { 
       
   271 return 
       
   272     lambda_functor_base<
       
   273       action<1, voidifier_action>,
       
   274       tuple<lambda_functor<Arg1> >
       
   275     > 
       
   276   (tuple<lambda_functor<Arg1> > (a1));
       
   277 }
       
   278 
       
   279 // for non-lambda functors, make_void does nothing 
       
   280 // (the argument gets evaluated immediately)
       
   281 
       
   282 template<class Arg1>
       
   283 inline const 
       
   284 lambda_functor<
       
   285   lambda_functor_base<do_nothing_action, null_type> 
       
   286 > 
       
   287 make_void(const Arg1& a1) { 
       
   288 return 
       
   289     lambda_functor_base<do_nothing_action, null_type>();
       
   290 }
       
   291 
       
   292 // std_functor -----------------------------------------------------
       
   293 
       
   294 //  The STL uses the result_type typedef as the convention to let binders know
       
   295 //  the return type of a function object. 
       
   296 //  LL uses the sig template.
       
   297 //  To let LL know that the function object has the result_type typedef 
       
   298 //  defined, it can be wrapped with the std_functor function.
       
   299 
       
   300 
       
   301 // Just inherit form the template parameter (the standard functor), 
       
   302 // and provide a sig template. So we have a class which is still the
       
   303 // same functor + the sig template.
       
   304 
       
   305 template<class T>
       
   306 struct result_type_to_sig : public T {
       
   307   template<class Args> struct sig { typedef typename T::result_type type; };
       
   308   result_type_to_sig(const T& t) : T(t) {}
       
   309 };
       
   310 
       
   311 template<class F>
       
   312 inline result_type_to_sig<F> std_functor(const F& f) { return f; }
       
   313 
       
   314 
       
   315 } // namespace lambda 
       
   316 } // namespace boost
       
   317 
       
   318 #endif
       
   319 
       
   320 
       
   321 
       
   322 
       
   323 
       
   324 
       
   325