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