2
0
mirror of https://github.com/boostorg/lambda.git synced 2026-01-28 07:12:20 +00:00
Files
lambda/include/boost/lambda/detail/lambda_functor_base.hpp
2001-12-21 19:28:31 +00:00

372 lines
16 KiB
C++

// Boost Lambda Library lambda_functor_base.hpp -----------------------------
//
// Copyright (C) 1999, 2000 Jaakko Järvi (jaakko.jarvi@cs.utu.fi)
//
// Permission to copy, use, sell and distribute this software is granted
// provided this copyright notice appears in all copies.
// Permission to modify the code and to distribute modified code is granted
// provided this copyright notice appears in all copies, and a notice
// that the code was modified is included with the copyright notice.
//
// This software is provided "as is" without express or implied warranty,
// and with no claim as to its suitability for any purpose.
//
// For more information, see www.boost.org
// ------------------------------------------------------------
#ifndef BOOST_LAMBDA_LAMBDA_FUNCTOR_BASE_HPP
#define BOOST_LAMBDA_LAMBDA_FUNCTOR_BASE_HPP
namespace boost {
namespace lambda {
namespace detail {
// In a call make_rvalues_const<T>::exec(x)
// x should be of type T. If T is a non-reference type, exec
// returns x as const reference.
// Otherwise the type doesn't change.
// The purpose of this class is to avoid
// 'cannot bind temporaries to non-const references' errors.
template <class T> struct make_rvalues_const {
template<class U>
static const U& exec(const U& u) { return u; }
};
template <class T> struct make_rvalues_const<T&> {
template<class U>
static U& exec(U& u) { return u; }
};
template <int N, class Args, class A, class B, class C>
struct nth_return_type {
typedef typename
return_type<
typename tuple_element_as_reference<N, Args>::type,
open_args<A, B, C>
>::type type;
};
} // end detail
// -- lambda_functor base ---------------------
// the explicit_return_type_action case -----------------------------------
template<class RET, class Args>
class lambda_functor_base<action<1, explicit_return_type_action<RET> >, Args>
{
public:
Args args;
public:
typedef RET result_type;
explicit lambda_functor_base(const Args& a) : args(a) {}
template<class RET_, class A, class B, class C>
RET call(A& a, B& b, C& c) const
// TODO: RET and RET_ should be the same type, add a compile time assert?
{
return detail::make_rvalues_const<RET>::exec(
detail::ret_selector<RET>::select(boost::tuples::get<0>(args), a, b, c));
}
};
// the protect_action case -----------------------------------
template<class Args>
class lambda_functor_base<action<1, protect_action >, Args>
{
public:
Args args;
public:
explicit lambda_functor_base(const Args& a) : args(a) {}
template<class RET, class A, class B, class C>
RET call(A& a, B& b, C& c) const
{
return boost::tuples::get<0>(args);
}
};
// The work of curry action is not defined in action class apply,
// but rather directly in lambda_functor_base::call
// The argument substitution would be messed up otherwise.
// the curry_action 2-ary lambda_functor, one curried arg -------------------
template<class Args>
class lambda_functor_base<action<3, curry_action<1> >, Args>
{
public:
Args args;
public:
explicit lambda_functor_base(const Args& a) : args(a) {}
template<class RET, class A, class B, class C>
RET call(A& a, B& b, C& c) const
{
return boost::tuples::get<0>(args).template ret_call<RET>(
boost::tuples::get<1>(args), a);
}
};
// the curry_action case, 3-ary lambda functor, one curried arg --------------
template<class Args>
class lambda_functor_base<action<4, curry_action<1> >, Args>
{
public:
Args args;
public:
explicit lambda_functor_base(const Args& a) : args(a) {}
template<class RET, class A, class B, class C>
RET call(A& a, B& b, C& c) const
{
return boost::tuples::get<0>(args).template ret_call<RET>(
boost::tuples::get<1>(args), a, b);
}
};
// the curry_action case, 3-ary lambda functor, two curried args -------------
template<class Args>
class lambda_functor_base<action<4, curry_action<2> >, Args>
{
public:
Args args;
public:
explicit lambda_functor_base(const Args& a) : args(a) {}
template<class RET, class A, class B, class C>
RET call(A& a, B& b, C& c) const
{
return boost::tuples::get<0>(args).template ret_call<RET>(
boost::tuples::get<1>(args), boost::tuples::get<2>(args), a);
}
};
#if defined BOOST_LAMBDA_LAMBDA_FUNCTOR_BASE_FIRST_PART
#error "Multiple defines of BOOST_LAMBDA_LAMBDA_FUNCTOR_BASE_FIRST_PART"
#endif
#define BOOST_LAMBDA_LAMBDA_FUNCTOR_BASE_FIRST_PART(ARITY) \
template<class Act, class Args>\
class lambda_functor_base<action<ARITY, Act>, Args> \
{\
public:\
Args args;\
public:\
\
explicit lambda_functor_base(const Args& a) : args(a) {}\
\
template<class RET, class A, class B, class C>\
RET call(A& a, B& b, C& c) const {\
\
BOOST_LAMBDA_LAMBDA_FUNCTOR_BASE_FIRST_PART(0)
return Act::template apply<RET>(
);
}
};
BOOST_LAMBDA_LAMBDA_FUNCTOR_BASE_FIRST_PART(1)
typedef typename detail::nth_return_type<0, Args, A&, B&, C&>::type ret0;
return Act::template apply<RET>(
detail::make_rvalues_const<ret0>::exec(detail::ret_selector<ret0>::select(boost::tuples::get<0>(args), a, b, c))
);
}
};
BOOST_LAMBDA_LAMBDA_FUNCTOR_BASE_FIRST_PART(2)
typedef typename detail::nth_return_type<0, Args, A&, B&, C&>::type ret0;
typedef typename detail::nth_return_type<1, Args, A&, B&, C&>::type ret1;
return Act::template apply<RET>(
detail::make_rvalues_const<ret0>::exec(detail::ret_selector<ret0>::select(boost::tuples::get<0>(args), a, b, c)),
detail::make_rvalues_const<ret1>::exec(detail::ret_selector<ret1>::select(boost::tuples::get<1>(args), a, b, c))
);
}
};
BOOST_LAMBDA_LAMBDA_FUNCTOR_BASE_FIRST_PART(3)
typedef typename detail::nth_return_type<0, Args, A&, B&, C&>::type ret0;
typedef typename detail::nth_return_type<1, Args, A&, B&, C&>::type ret1;
typedef typename detail::nth_return_type<2, Args, A&, B&, C&>::type ret2;
return Act::template apply<RET>(
detail::make_rvalues_const<ret0>::exec(detail::ret_selector<ret0>::select(boost::tuples::get<0>(args), a, b, c)),
detail::make_rvalues_const<ret1>::exec(detail::ret_selector<ret1>::select(boost::tuples::get<1>(args), a, b, c)),
detail::make_rvalues_const<ret2>::exec(detail::ret_selector<ret2>::select(boost::tuples::get<2>(args), a, b, c))
);
}
};
BOOST_LAMBDA_LAMBDA_FUNCTOR_BASE_FIRST_PART(4)
typedef typename detail::nth_return_type<0, Args, A&, B&, C&>::type ret0;
typedef typename detail::nth_return_type<1, Args, A&, B&, C&>::type ret1;
typedef typename detail::nth_return_type<2, Args, A&, B&, C&>::type ret2;
typedef typename detail::nth_return_type<3, Args, A&, B&, C&>::type ret3;
return Act::template apply<RET>(
detail::make_rvalues_const<ret0>::exec(detail::ret_selector<ret0>::select(boost::tuples::get<0>(args), a, b, c)),
detail::make_rvalues_const<ret1>::exec(detail::ret_selector<ret1>::select(boost::tuples::get<1>(args), a, b, c)),
detail::make_rvalues_const<ret2>::exec(detail::ret_selector<ret2>::select(boost::tuples::get<2>(args), a, b, c)),
detail::make_rvalues_const<ret3>::exec(detail::ret_selector<ret3>::select(boost::tuples::get<3>(args), a, b, c))
);
}
};
BOOST_LAMBDA_LAMBDA_FUNCTOR_BASE_FIRST_PART(5)
typedef typename detail::nth_return_type<0, Args, A&, B&, C&>::type ret0;
typedef typename detail::nth_return_type<1, Args, A&, B&, C&>::type ret1;
typedef typename detail::nth_return_type<2, Args, A&, B&, C&>::type ret2;
typedef typename detail::nth_return_type<3, Args, A&, B&, C&>::type ret3;
typedef typename detail::nth_return_type<4, Args, A&, B&, C&>::type ret4;
return Act::template apply<RET>(
detail::make_rvalues_const<ret0>::exec(detail::ret_selector<ret0>::select(boost::tuples::get<0>(args), a, b, c)),
detail::make_rvalues_const<ret1>::exec(detail::ret_selector<ret1>::select(boost::tuples::get<1>(args), a, b, c)),
detail::make_rvalues_const<ret2>::exec(detail::ret_selector<ret2>::select(boost::tuples::get<2>(args), a, b, c)),
detail::make_rvalues_const<ret3>::exec(detail::ret_selector<ret3>::select(boost::tuples::get<3>(args), a, b, c)),
detail::make_rvalues_const<ret4>::exec(detail::ret_selector<ret4>::select(boost::tuples::get<4>(args), a, b, c))
);
}
};
BOOST_LAMBDA_LAMBDA_FUNCTOR_BASE_FIRST_PART(6)
typedef typename detail::nth_return_type<0, Args, A&, B&, C&>::type ret0;
typedef typename detail::nth_return_type<1, Args, A&, B&, C&>::type ret1;
typedef typename detail::nth_return_type<2, Args, A&, B&, C&>::type ret2;
typedef typename detail::nth_return_type<3, Args, A&, B&, C&>::type ret3;
typedef typename detail::nth_return_type<4, Args, A&, B&, C&>::type ret4;
typedef typename detail::nth_return_type<5, Args, A&, B&, C&>::type ret5;
return Act::template apply<RET>(
detail::make_rvalues_const<ret0>::exec(detail::ret_selector<ret0>::select(boost::tuples::get<0>(args), a, b, c)),
detail::make_rvalues_const<ret1>::exec(detail::ret_selector<ret1>::select(boost::tuples::get<1>(args), a, b, c)),
detail::make_rvalues_const<ret2>::exec(detail::ret_selector<ret2>::select(boost::tuples::get<2>(args), a, b, c)),
detail::make_rvalues_const<ret3>::exec(detail::ret_selector<ret3>::select(boost::tuples::get<3>(args), a, b, c)),
detail::make_rvalues_const<ret4>::exec(detail::ret_selector<ret4>::select(boost::tuples::get<4>(args), a, b, c)),
detail::make_rvalues_const<ret5>::exec(detail::ret_selector<ret5>::select(boost::tuples::get<5>(args), a, b, c))
);
}
};
BOOST_LAMBDA_LAMBDA_FUNCTOR_BASE_FIRST_PART(7)
typedef typename detail::nth_return_type<0, Args, A&, B&, C&>::type ret0;
typedef typename detail::nth_return_type<1, Args, A&, B&, C&>::type ret1;
typedef typename detail::nth_return_type<2, Args, A&, B&, C&>::type ret2;
typedef typename detail::nth_return_type<3, Args, A&, B&, C&>::type ret3;
typedef typename detail::nth_return_type<4, Args, A&, B&, C&>::type ret4;
typedef typename detail::nth_return_type<5, Args, A&, B&, C&>::type ret5;
typedef typename detail::nth_return_type<6, Args, A&, B&, C&>::type ret6;
return Act::template apply<RET>(
detail::make_rvalues_const<ret0>::exec(detail::ret_selector<ret0>::select(boost::tuples::get<0>(args), a, b, c)),
detail::make_rvalues_const<ret1>::exec(detail::ret_selector<ret1>::select(boost::tuples::get<1>(args), a, b, c)),
detail::make_rvalues_const<ret2>::exec(detail::ret_selector<ret2>::select(boost::tuples::get<2>(args), a, b, c)),
detail::make_rvalues_const<ret3>::exec(detail::ret_selector<ret3>::select(boost::tuples::get<3>(args), a, b, c)),
detail::make_rvalues_const<ret4>::exec(detail::ret_selector<ret4>::select(boost::tuples::get<4>(args), a, b, c)),
detail::make_rvalues_const<ret5>::exec(detail::ret_selector<ret5>::select(boost::tuples::get<5>(args), a, b, c)),
detail::make_rvalues_const<ret6>::exec(detail::ret_selector<ret6>::select(boost::tuples::get<6>(args), a, b, c))
);
}
};
BOOST_LAMBDA_LAMBDA_FUNCTOR_BASE_FIRST_PART(8)
typedef typename detail::nth_return_type<0, Args, A&, B&, C&>::type ret0;
typedef typename detail::nth_return_type<1, Args, A&, B&, C&>::type ret1;
typedef typename detail::nth_return_type<2, Args, A&, B&, C&>::type ret2;
typedef typename detail::nth_return_type<3, Args, A&, B&, C&>::type ret3;
typedef typename detail::nth_return_type<4, Args, A&, B&, C&>::type ret4;
typedef typename detail::nth_return_type<5, Args, A&, B&, C&>::type ret5;
typedef typename detail::nth_return_type<6, Args, A&, B&, C&>::type ret6;
typedef typename detail::nth_return_type<7, Args, A&, B&, C&>::type ret7;
return Act::template apply<RET>(
detail::make_rvalues_const<ret0>::exec(detail::ret_selector<ret0>::select(boost::tuples::get<0>(args), a, b, c)),
detail::make_rvalues_const<ret1>::exec(detail::ret_selector<ret1>::select(boost::tuples::get<1>(args), a, b, c)),
detail::make_rvalues_const<ret2>::exec(detail::ret_selector<ret2>::select(boost::tuples::get<2>(args), a, b, c)),
detail::make_rvalues_const<ret3>::exec(detail::ret_selector<ret3>::select(boost::tuples::get<3>(args), a, b, c)),
detail::make_rvalues_const<ret4>::exec(detail::ret_selector<ret4>::select(boost::tuples::get<4>(args), a, b, c)),
detail::make_rvalues_const<ret5>::exec(detail::ret_selector<ret5>::select(boost::tuples::get<5>(args), a, b, c)),
detail::make_rvalues_const<ret6>::exec(detail::ret_selector<ret6>::select(boost::tuples::get<6>(args), a, b, c)),
detail::make_rvalues_const<ret7>::exec(detail::ret_selector<ret7>::select(boost::tuples::get<7>(args), a, b, c))
);
}
};
BOOST_LAMBDA_LAMBDA_FUNCTOR_BASE_FIRST_PART(9)
typedef typename detail::nth_return_type<0, Args, A&, B&, C&>::type ret0;
typedef typename detail::nth_return_type<1, Args, A&, B&, C&>::type ret1;
typedef typename detail::nth_return_type<2, Args, A&, B&, C&>::type ret2;
typedef typename detail::nth_return_type<3, Args, A&, B&, C&>::type ret3;
typedef typename detail::nth_return_type<4, Args, A&, B&, C&>::type ret4;
typedef typename detail::nth_return_type<5, Args, A&, B&, C&>::type ret5;
typedef typename detail::nth_return_type<6, Args, A&, B&, C&>::type ret6;
typedef typename detail::nth_return_type<7, Args, A&, B&, C&>::type ret7;
typedef typename detail::nth_return_type<8, Args, A&, B&, C&>::type ret8;
return Act::template apply<RET>(
detail::make_rvalues_const<ret0>::exec(detail::ret_selector<ret0>::select(boost::tuples::get<0>(args), a, b, c)),
detail::make_rvalues_const<ret1>::exec(detail::ret_selector<ret1>::select(boost::tuples::get<1>(args), a, b, c)),
detail::make_rvalues_const<ret2>::exec(detail::ret_selector<ret2>::select(boost::tuples::get<2>(args), a, b, c)),
detail::make_rvalues_const<ret3>::exec(detail::ret_selector<ret3>::select(boost::tuples::get<3>(args), a, b, c)),
detail::make_rvalues_const<ret4>::exec(detail::ret_selector<ret4>::select(boost::tuples::get<4>(args), a, b, c)),
detail::make_rvalues_const<ret5>::exec(detail::ret_selector<ret5>::select(boost::tuples::get<5>(args), a, b, c)),
detail::make_rvalues_const<ret6>::exec(detail::ret_selector<ret6>::select(boost::tuples::get<6>(args), a, b, c)),
detail::make_rvalues_const<ret7>::exec(detail::ret_selector<ret7>::select(boost::tuples::get<7>(args), a, b, c)),
detail::make_rvalues_const<ret8>::exec(detail::ret_selector<ret8>::select(boost::tuples::get<8>(args), a, b, c))
);
}
};
BOOST_LAMBDA_LAMBDA_FUNCTOR_BASE_FIRST_PART(10)
typedef typename detail::nth_return_type<0, Args, A&, B&, C&>::type ret0;
typedef typename detail::nth_return_type<1, Args, A&, B&, C&>::type ret1;
typedef typename detail::nth_return_type<2, Args, A&, B&, C&>::type ret2;
typedef typename detail::nth_return_type<3, Args, A&, B&, C&>::type ret3;
typedef typename detail::nth_return_type<4, Args, A&, B&, C&>::type ret4;
typedef typename detail::nth_return_type<5, Args, A&, B&, C&>::type ret5;
typedef typename detail::nth_return_type<6, Args, A&, B&, C&>::type ret6;
typedef typename detail::nth_return_type<7, Args, A&, B&, C&>::type ret7;
typedef typename detail::nth_return_type<8, Args, A&, B&, C&>::type ret8;
typedef typename detail::nth_return_type<9, Args, A&, B&, C&>::type ret9;
return Act::template apply<RET>(
detail::make_rvalues_const<ret0>::exec(detail::ret_selector<ret0>::select(boost::tuples::get<0>(args), a, b, c)),
detail::make_rvalues_const<ret1>::exec(detail::ret_selector<ret1>::select(boost::tuples::get<1>(args), a, b, c)),
detail::make_rvalues_const<ret2>::exec(detail::ret_selector<ret2>::select(boost::tuples::get<2>(args), a, b, c)),
detail::make_rvalues_const<ret3>::exec(detail::ret_selector<ret3>::select(boost::tuples::get<3>(args), a, b, c)),
detail::make_rvalues_const<ret4>::exec(detail::ret_selector<ret4>::select(boost::tuples::get<4>(args), a, b, c)),
detail::make_rvalues_const<ret5>::exec(detail::ret_selector<ret5>::select(boost::tuples::get<5>(args), a, b, c)),
detail::make_rvalues_const<ret6>::exec(detail::ret_selector<ret6>::select(boost::tuples::get<6>(args), a, b, c)),
detail::make_rvalues_const<ret7>::exec(detail::ret_selector<ret7>::select(boost::tuples::get<7>(args), a, b, c)),
detail::make_rvalues_const<ret8>::exec(detail::ret_selector<ret8>::select(boost::tuples::get<8>(args), a, b, c)),
detail::make_rvalues_const<ret9>::exec(detail::ret_selector<ret9>::select(boost::tuples::get<9>(args), a, b, c))
);
}
};
#undef BOOST_LAMBDA_LAMBDA_FUNCTOR_BASE_FIRST_PART
} // namespace lambda
} // namespace boost
#endif