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