506 lines
14 KiB
C++
506 lines
14 KiB
C++
// Boost Lambda Library -- loops.hpp ----------------------------------------
|
|
|
|
// Copyright (C) 1999, 2000 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi)
|
|
// Copyright (C) 2000 Gary Powell (powellg@amazon.com)
|
|
// Copyright (c) 2001-2002 Joel de Guzman
|
|
//
|
|
// Distributed under the Boost Software License, Version 1.0. (See
|
|
// accompanying file LICENSE_1_0.txt or copy at
|
|
// http://www.boost.org/LICENSE_1_0.txt)
|
|
//
|
|
// For more information, see www.boost.org
|
|
|
|
// --------------------------------------------------------------------------
|
|
|
|
#if !defined(BOOST_LAMBDA_LOOPS_HPP)
|
|
#define BOOST_LAMBDA_LOOPS_HPP
|
|
|
|
#include "boost/lambda/core.hpp"
|
|
|
|
namespace boost {
|
|
namespace lambda {
|
|
|
|
// -- loop control structure actions ----------------------
|
|
|
|
class forloop_action {};
|
|
class forloop_no_body_action {};
|
|
class whileloop_action {};
|
|
class whileloop_no_body_action {};
|
|
class dowhileloop_action {};
|
|
class dowhileloop_no_body_action {};
|
|
|
|
|
|
// For loop
|
|
template <class Arg1, class Arg2, class Arg3, class Arg4>
|
|
inline const
|
|
lambda_functor<
|
|
lambda_functor_base<
|
|
forloop_action,
|
|
tuple<lambda_functor<Arg1>, lambda_functor<Arg2>,
|
|
lambda_functor<Arg3>, lambda_functor<Arg4> >
|
|
>
|
|
>
|
|
for_loop(const lambda_functor<Arg1>& a1, const lambda_functor<Arg2>& a2,
|
|
const lambda_functor<Arg3>& a3, const lambda_functor<Arg4>& a4) {
|
|
return
|
|
lambda_functor_base<
|
|
forloop_action,
|
|
tuple<lambda_functor<Arg1>, lambda_functor<Arg2>,
|
|
lambda_functor<Arg3>, lambda_functor<Arg4> >
|
|
>
|
|
( tuple<lambda_functor<Arg1>, lambda_functor<Arg2>,
|
|
lambda_functor<Arg3>, lambda_functor<Arg4> >(a1, a2, a3, a4)
|
|
);
|
|
}
|
|
|
|
// No body case.
|
|
template <class Arg1, class Arg2, class Arg3>
|
|
inline const
|
|
lambda_functor<
|
|
lambda_functor_base<
|
|
forloop_no_body_action,
|
|
tuple<lambda_functor<Arg1>, lambda_functor<Arg2>, lambda_functor<Arg3> >
|
|
>
|
|
>
|
|
for_loop(const lambda_functor<Arg1>& a1, const lambda_functor<Arg2>& a2,
|
|
const lambda_functor<Arg3>& a3) {
|
|
return
|
|
lambda_functor_base<
|
|
forloop_no_body_action,
|
|
tuple<lambda_functor<Arg1>, lambda_functor<Arg2>,
|
|
lambda_functor<Arg3> >
|
|
>
|
|
( tuple<lambda_functor<Arg1>, lambda_functor<Arg2>,
|
|
lambda_functor<Arg3> >(a1, a2, a3) );
|
|
}
|
|
|
|
// While loop
|
|
template <class Arg1, class Arg2>
|
|
inline const
|
|
lambda_functor<
|
|
lambda_functor_base<
|
|
whileloop_action,
|
|
tuple<lambda_functor<Arg1>, lambda_functor<Arg2> >
|
|
>
|
|
>
|
|
while_loop(const lambda_functor<Arg1>& a1, const lambda_functor<Arg2>& a2) {
|
|
return
|
|
lambda_functor_base<
|
|
whileloop_action,
|
|
tuple<lambda_functor<Arg1>, lambda_functor<Arg2> >
|
|
>
|
|
( tuple<lambda_functor<Arg1>, lambda_functor<Arg2> >(a1, a2));
|
|
}
|
|
|
|
// No body case.
|
|
template <class Arg1>
|
|
inline const
|
|
lambda_functor<
|
|
lambda_functor_base<
|
|
whileloop_no_body_action,
|
|
tuple<lambda_functor<Arg1> >
|
|
>
|
|
>
|
|
while_loop(const lambda_functor<Arg1>& a1) {
|
|
return
|
|
lambda_functor_base<
|
|
whileloop_no_body_action,
|
|
tuple<lambda_functor<Arg1> >
|
|
>
|
|
( tuple<lambda_functor<Arg1> >(a1) );
|
|
}
|
|
|
|
|
|
// Do While loop
|
|
template <class Arg1, class Arg2>
|
|
inline const
|
|
lambda_functor<
|
|
lambda_functor_base<
|
|
dowhileloop_action,
|
|
tuple<lambda_functor<Arg1>, lambda_functor<Arg2> >
|
|
>
|
|
>
|
|
do_while_loop(const lambda_functor<Arg1>& a1, const lambda_functor<Arg2>& a2) {
|
|
return
|
|
lambda_functor_base<
|
|
dowhileloop_action,
|
|
tuple<lambda_functor<Arg1>, lambda_functor<Arg2> >
|
|
>
|
|
( tuple<lambda_functor<Arg1>, lambda_functor<Arg2> >(a1, a2));
|
|
}
|
|
|
|
// No body case.
|
|
template <class Arg1>
|
|
inline const
|
|
lambda_functor<
|
|
lambda_functor_base<
|
|
dowhileloop_no_body_action,
|
|
tuple<lambda_functor<Arg1> >
|
|
>
|
|
>
|
|
do_while_loop(const lambda_functor<Arg1>& a1) {
|
|
return
|
|
lambda_functor_base<
|
|
dowhileloop_no_body_action,
|
|
tuple<lambda_functor<Arg1> >
|
|
>
|
|
( tuple<lambda_functor<Arg1> >(a1));
|
|
}
|
|
|
|
|
|
// Control loop lambda_functor_base specializations.
|
|
|
|
// Specialization for for_loop.
|
|
template<class Args>
|
|
class
|
|
lambda_functor_base<forloop_action, Args> {
|
|
public:
|
|
Args args;
|
|
template <class T> struct sig { typedef void type; };
|
|
public:
|
|
explicit lambda_functor_base(const Args& a) : args(a) {}
|
|
|
|
template<class RET, CALL_TEMPLATE_ARGS>
|
|
RET call(CALL_FORMAL_ARGS) const {
|
|
for(detail::select(boost::tuples::get<0>(args), CALL_ACTUAL_ARGS);
|
|
detail::select(boost::tuples::get<1>(args), CALL_ACTUAL_ARGS);
|
|
detail::select(boost::tuples::get<2>(args), CALL_ACTUAL_ARGS))
|
|
|
|
detail::select(boost::tuples::get<3>(args), CALL_ACTUAL_ARGS);
|
|
}
|
|
};
|
|
|
|
// No body case
|
|
template<class Args>
|
|
class
|
|
lambda_functor_base<forloop_no_body_action, Args> {
|
|
public:
|
|
Args args;
|
|
template <class T> struct sig { typedef void type; };
|
|
public:
|
|
explicit lambda_functor_base(const Args& a) : args(a) {}
|
|
|
|
template<class RET, CALL_TEMPLATE_ARGS>
|
|
RET call(CALL_FORMAL_ARGS) const {
|
|
for(detail::select(boost::tuples::get<0>(args), CALL_ACTUAL_ARGS);
|
|
detail::select(boost::tuples::get<1>(args), CALL_ACTUAL_ARGS);
|
|
detail::select(boost::tuples::get<2>(args), CALL_ACTUAL_ARGS)) {}
|
|
}
|
|
};
|
|
|
|
|
|
// Specialization for while_loop.
|
|
template<class Args>
|
|
class
|
|
lambda_functor_base<whileloop_action, Args> {
|
|
public:
|
|
Args args;
|
|
template <class T> struct sig { typedef void type; };
|
|
public:
|
|
explicit lambda_functor_base(const Args& a) : args(a) {}
|
|
|
|
template<class RET, CALL_TEMPLATE_ARGS>
|
|
RET call(CALL_FORMAL_ARGS) const {
|
|
while(detail::select(boost::tuples::get<0>(args), CALL_ACTUAL_ARGS))
|
|
|
|
detail::select(boost::tuples::get<1>(args), CALL_ACTUAL_ARGS);
|
|
}
|
|
};
|
|
|
|
// No body case
|
|
template<class Args>
|
|
class
|
|
lambda_functor_base<whileloop_no_body_action, Args> {
|
|
public:
|
|
Args args;
|
|
template <class T> struct sig { typedef void type; };
|
|
public:
|
|
explicit lambda_functor_base(const Args& a) : args(a) {}
|
|
|
|
template<class RET, CALL_TEMPLATE_ARGS>
|
|
RET call(CALL_FORMAL_ARGS) const {
|
|
while(detail::select(boost::tuples::get<0>(args), CALL_ACTUAL_ARGS)) {}
|
|
}
|
|
};
|
|
|
|
// Specialization for do_while_loop.
|
|
// Note that the first argument is the condition.
|
|
template<class Args>
|
|
class
|
|
lambda_functor_base<dowhileloop_action, Args> {
|
|
public:
|
|
Args args;
|
|
template <class T> struct sig { typedef void type; };
|
|
public:
|
|
explicit lambda_functor_base(const Args& a) : args(a) {}
|
|
|
|
template<class RET, CALL_TEMPLATE_ARGS>
|
|
RET call(CALL_FORMAL_ARGS) const {
|
|
do {
|
|
detail::select(boost::tuples::get<1>(args), CALL_ACTUAL_ARGS);
|
|
} while (detail::select(boost::tuples::get<0>(args), CALL_ACTUAL_ARGS) );
|
|
}
|
|
};
|
|
|
|
// No body case
|
|
template<class Args>
|
|
class
|
|
lambda_functor_base<dowhileloop_no_body_action, Args> {
|
|
public:
|
|
Args args;
|
|
template <class T> struct sig { typedef void type; };
|
|
public:
|
|
explicit lambda_functor_base(const Args& a) : args(a) {}
|
|
|
|
template<class RET, CALL_TEMPLATE_ARGS>
|
|
RET call(CALL_FORMAL_ARGS) const {
|
|
do {} while (detail::select(boost::tuples::get<0>(args), CALL_ACTUAL_ARGS) );
|
|
}
|
|
};
|
|
|
|
// The code below is from Joel de Guzman, some name changes etc.
|
|
// has been made.
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// while_composite
|
|
//
|
|
// This composite has the form:
|
|
//
|
|
// while_(condition)
|
|
// [
|
|
// statement
|
|
// ]
|
|
//
|
|
// While the condition (an lambda_functor) evaluates to true, statement
|
|
// (another lambda_functor) is executed. The result type of this is void.
|
|
// Note the trailing underscore after while_.
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
template <typename CondT, typename DoT>
|
|
struct while_composite {
|
|
|
|
typedef while_composite<CondT, DoT> self_t;
|
|
|
|
template <class SigArgs>
|
|
struct sig { typedef void type; };
|
|
|
|
while_composite(CondT const& cond_, DoT const& do__)
|
|
: cond(cond_), do_(do__) {}
|
|
|
|
template <class Ret, CALL_TEMPLATE_ARGS>
|
|
Ret call(CALL_FORMAL_ARGS) const
|
|
{
|
|
while (cond.internal_call(CALL_ACTUAL_ARGS))
|
|
do_.internal_call(CALL_ACTUAL_ARGS);
|
|
}
|
|
|
|
CondT cond;
|
|
DoT do_;
|
|
};
|
|
|
|
//////////////////////////////////
|
|
template <typename CondT>
|
|
struct while_gen {
|
|
|
|
while_gen(CondT const& cond_)
|
|
: cond(cond_) {}
|
|
|
|
template <typename DoT>
|
|
lambda_functor<while_composite<
|
|
typename as_lambda_functor<CondT>::type,
|
|
typename as_lambda_functor<DoT>::type> >
|
|
operator[](DoT const& do_) const
|
|
{
|
|
typedef while_composite<
|
|
typename as_lambda_functor<CondT>::type,
|
|
typename as_lambda_functor<DoT>::type>
|
|
result;
|
|
|
|
return result(
|
|
to_lambda_functor(cond),
|
|
to_lambda_functor(do_));
|
|
}
|
|
|
|
CondT cond;
|
|
};
|
|
|
|
//////////////////////////////////
|
|
template <typename CondT>
|
|
inline while_gen<CondT>
|
|
while_(CondT const& cond)
|
|
{
|
|
return while_gen<CondT>(cond);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// do_composite
|
|
//
|
|
// This composite has the form:
|
|
//
|
|
// do_
|
|
// [
|
|
// statement
|
|
// ]
|
|
// .while_(condition)
|
|
//
|
|
// While the condition (an lambda_functor) evaluates to true, statement
|
|
// (another lambda_functor) is executed. The statement is executed at least
|
|
// once. The result type of this is void. Note the trailing
|
|
// underscore after do_ and the leading dot and the trailing
|
|
// underscore before and after .while_.
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
template <typename DoT, typename CondT>
|
|
struct do_composite {
|
|
|
|
typedef do_composite<DoT, CondT> self_t;
|
|
|
|
template <class SigArgs>
|
|
struct sig { typedef void type; };
|
|
|
|
do_composite(DoT const& do__, CondT const& cond_)
|
|
: do_(do__), cond(cond_) {}
|
|
|
|
template <class Ret, CALL_TEMPLATE_ARGS>
|
|
Ret call(CALL_FORMAL_ARGS) const
|
|
{
|
|
do
|
|
do_.internal_call(CALL_ACTUAL_ARGS);
|
|
while (cond.internal_call(CALL_ACTUAL_ARGS));
|
|
}
|
|
|
|
DoT do_;
|
|
CondT cond;
|
|
};
|
|
|
|
////////////////////////////////////
|
|
template <typename DoT>
|
|
struct do_gen2 {
|
|
|
|
do_gen2(DoT const& do__)
|
|
: do_(do__) {}
|
|
|
|
template <typename CondT>
|
|
lambda_functor<do_composite<
|
|
typename as_lambda_functor<DoT>::type,
|
|
typename as_lambda_functor<CondT>::type> >
|
|
while_(CondT const& cond) const
|
|
{
|
|
typedef do_composite<
|
|
typename as_lambda_functor<DoT>::type,
|
|
typename as_lambda_functor<CondT>::type>
|
|
result;
|
|
|
|
return result(
|
|
to_lambda_functor(do_),
|
|
to_lambda_functor(cond));
|
|
}
|
|
|
|
DoT do_;
|
|
};
|
|
|
|
////////////////////////////////////
|
|
struct do_gen {
|
|
|
|
template <typename DoT>
|
|
do_gen2<DoT>
|
|
operator[](DoT const& do_) const
|
|
{
|
|
return do_gen2<DoT>(do_);
|
|
}
|
|
};
|
|
|
|
do_gen const do_ = do_gen();
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// for_composite
|
|
//
|
|
// This statement has the form:
|
|
//
|
|
// for_(init, condition, step)
|
|
// [
|
|
// statement
|
|
// ]
|
|
//
|
|
// Where init, condition, step and statement are all lambda_functors. init
|
|
// is executed once before entering the for-loop. The for-loop
|
|
// exits once condition evaluates to false. At each loop iteration,
|
|
// step and statement is called. The result of this statement is
|
|
// void. Note the trailing underscore after for_.
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
template <typename InitT, typename CondT, typename StepT, typename DoT>
|
|
struct for_composite {
|
|
|
|
template <class SigArgs>
|
|
struct sig { typedef void type; };
|
|
|
|
for_composite(
|
|
InitT const& init_,
|
|
CondT const& cond_,
|
|
StepT const& step_,
|
|
DoT const& do__)
|
|
: init(init_), cond(cond_), step(step_), do_(do__) {}
|
|
|
|
template <class Ret, CALL_TEMPLATE_ARGS>
|
|
Ret
|
|
call(CALL_FORMAL_ARGS) const
|
|
{
|
|
for (init.internal_call(CALL_ACTUAL_ARGS); cond.internal_call(CALL_ACTUAL_ARGS); step.internal_call(CALL_ACTUAL_ARGS))
|
|
do_.internal_call(CALL_ACTUAL_ARGS);
|
|
}
|
|
|
|
InitT init; CondT cond; StepT step; DoT do_; // lambda_functors
|
|
};
|
|
|
|
//////////////////////////////////
|
|
template <typename InitT, typename CondT, typename StepT>
|
|
struct for_gen {
|
|
|
|
for_gen(
|
|
InitT const& init_,
|
|
CondT const& cond_,
|
|
StepT const& step_)
|
|
: init(init_), cond(cond_), step(step_) {}
|
|
|
|
template <typename DoT>
|
|
lambda_functor<for_composite<
|
|
typename as_lambda_functor<InitT>::type,
|
|
typename as_lambda_functor<CondT>::type,
|
|
typename as_lambda_functor<StepT>::type,
|
|
typename as_lambda_functor<DoT>::type> >
|
|
operator[](DoT const& do_) const
|
|
{
|
|
typedef for_composite<
|
|
typename as_lambda_functor<InitT>::type,
|
|
typename as_lambda_functor<CondT>::type,
|
|
typename as_lambda_functor<StepT>::type,
|
|
typename as_lambda_functor<DoT>::type>
|
|
result;
|
|
|
|
return result(
|
|
to_lambda_functor(init),
|
|
to_lambda_functor(cond),
|
|
to_lambda_functor(step),
|
|
to_lambda_functor(do_));
|
|
}
|
|
|
|
InitT init; CondT cond; StepT step;
|
|
};
|
|
|
|
//////////////////////////////////
|
|
template <typename InitT, typename CondT, typename StepT>
|
|
inline for_gen<InitT, CondT, StepT>
|
|
for_(InitT const& init, CondT const& cond, StepT const& step)
|
|
{
|
|
return for_gen<InitT, CondT, StepT>(init, cond, step);
|
|
}
|
|
|
|
} // lambda
|
|
} // boost
|
|
|
|
#endif // BOOST_LAMBDA_LOOPS_HPP
|