annotate DEPENDENCIES/generic/include/boost/lambda/detail/ret.hpp @ 133:4acb5d8d80b6 tip

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