mirror of
https://github.com/boostorg/lambda.git
synced 2026-01-21 04:52:25 +00:00
Compare commits
1 Commits
svn-branch
...
svn-branch
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
aa52de0931 |
@@ -142,7 +142,7 @@ struct transform : public has_sig {
|
||||
typedef typename boost::remove_const<
|
||||
typename boost::remove_reference<
|
||||
typename boost::tuples::element<
|
||||
boost::tuples::length<Args>::value - 2,
|
||||
boost::tuples::length<Args>::value - 1,
|
||||
Args
|
||||
>::type
|
||||
>::type
|
||||
|
||||
@@ -54,10 +54,9 @@ namespace lambda {
|
||||
|
||||
namespace {
|
||||
|
||||
// These are constants types and need to be initialised
|
||||
boost::lambda::placeholder1_type free1 = boost::lambda::placeholder1_type();
|
||||
boost::lambda::placeholder2_type free2 = boost::lambda::placeholder2_type();
|
||||
boost::lambda::placeholder3_type free3 = boost::lambda::placeholder3_type();
|
||||
boost::lambda::placeholder1_type free1;
|
||||
boost::lambda::placeholder2_type free2;
|
||||
boost::lambda::placeholder3_type free3;
|
||||
|
||||
boost::lambda::placeholder1_type& _1 = free1;
|
||||
boost::lambda::placeholder2_type& _2 = free2;
|
||||
|
||||
@@ -23,7 +23,7 @@ namespace lambda {
|
||||
|
||||
|
||||
|
||||
template<int Arity, class Act> class action;
|
||||
template<int Arity, class Act> struct action;
|
||||
|
||||
// these need to be defined here, since the corresponding lambda
|
||||
// functions are members of lambda_functor classes
|
||||
|
||||
@@ -30,9 +30,9 @@
|
||||
#endif // __GNUC__
|
||||
|
||||
|
||||
#if defined __KCC
|
||||
# if defined __KCC
|
||||
|
||||
#define BOOST_NO_FDECL_TEMPLATES_AS_TEMPLATE_TEMPLATE_PARAMS
|
||||
#define BOOST_NO_FORWARD_DECLARADED_TEMPLATES_AS_TEMPLATE_TEMPLATE_PARAMETERS
|
||||
|
||||
#endif // __KCC
|
||||
|
||||
|
||||
@@ -36,9 +36,6 @@ namespace {
|
||||
|
||||
#define const_null_type() detail::constant_null_type
|
||||
|
||||
|
||||
|
||||
|
||||
#if defined BOOST_LAMBDA_LAMBDA_FUNCTOR_ASSIGNMENT
|
||||
#error "Multiple defines of BOOST_LAMBDA_LAMBDA_FUNCTOR_ASSIGNMENT"
|
||||
#endif
|
||||
@@ -84,88 +81,20 @@ namespace {
|
||||
\
|
||||
|
||||
|
||||
// -- free variables types --------------------------------------------------
|
||||
|
||||
template <int I> class placeholder {};
|
||||
|
||||
typedef const lambda_functor<placeholder<FIRST> > placeholder1_type;
|
||||
typedef const lambda_functor<placeholder<SECOND> > placeholder2_type;
|
||||
typedef const lambda_functor<placeholder<THIRD> > placeholder3_type;
|
||||
|
||||
// free variables are lambda_functors. This is to allow uniform handling with
|
||||
// other lambda_functors.
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
|
||||
// template <int I>
|
||||
// class lambda_functor<placeholder<I> > {
|
||||
// public:
|
||||
// lambda_functor() {}
|
||||
// // (do nothing) bug in gcc 2.95.2 for const template objects.
|
||||
|
||||
// BOOST_LAMBDA_LAMBDA_FUNCTOR_ASSIGNMENT
|
||||
// BOOST_LAMBDA_LAMBDA_FUNCTOR_SUBSCRIPT
|
||||
// };
|
||||
|
||||
// covers _E, does not define (), cause it will only be called
|
||||
// inside of other lambda functors.
|
||||
template <int I>
|
||||
class lambda_functor<placeholder<I> > {
|
||||
public:
|
||||
lambda_functor() {}
|
||||
BOOST_LAMBDA_LAMBDA_FUNCTOR_ASSIGNMENT
|
||||
BOOST_LAMBDA_LAMBDA_FUNCTOR_SUBSCRIPT
|
||||
};
|
||||
|
||||
template<>
|
||||
class lambda_functor<placeholder<FIRST> > {
|
||||
public:
|
||||
lambda_functor() {}
|
||||
template <class A>
|
||||
A& operator()(A& a) const { return a; }
|
||||
// default constructor (do nothing)
|
||||
// bug in gcc 2.95.2 for const template objects.
|
||||
|
||||
|
||||
BOOST_LAMBDA_LAMBDA_FUNCTOR_ASSIGNMENT
|
||||
BOOST_LAMBDA_LAMBDA_FUNCTOR_SUBSCRIPT
|
||||
|
||||
|
||||
};
|
||||
|
||||
template<>
|
||||
class lambda_functor<placeholder<SECOND> > {
|
||||
public:
|
||||
lambda_functor() {}
|
||||
template <class A, class B>
|
||||
B& operator()(A&, B& b) const { return b; }
|
||||
|
||||
// currying call: creates another lambda functor
|
||||
template<class A>
|
||||
placeholder1_type
|
||||
operator()(A&) const { return _1; }
|
||||
|
||||
BOOST_LAMBDA_LAMBDA_FUNCTOR_ASSIGNMENT
|
||||
BOOST_LAMBDA_LAMBDA_FUNCTOR_SUBSCRIPT
|
||||
};
|
||||
|
||||
template<>
|
||||
class lambda_functor<placeholder<THIRD> > {
|
||||
public:
|
||||
lambda_functor() {}
|
||||
template <class A, class B, class C>
|
||||
C& operator()(A&, B&, C& c) const { return c; }
|
||||
|
||||
// currying calls: create another lambda functor
|
||||
template<class A>
|
||||
placeholder2_type
|
||||
operator()(A&) const { return _2; }
|
||||
|
||||
template<class A, class B>
|
||||
placeholder1_type
|
||||
operator()(A&, B&) const { return _1; }
|
||||
|
||||
|
||||
BOOST_LAMBDA_LAMBDA_FUNCTOR_ASSIGNMENT
|
||||
BOOST_LAMBDA_LAMBDA_FUNCTOR_SUBSCRIPT
|
||||
};
|
||||
|
||||
|
||||
namespace detail {
|
||||
|
||||
// helpers
|
||||
@@ -614,6 +543,17 @@ public:
|
||||
};
|
||||
|
||||
|
||||
// -- free variables types --------------------------------------------------
|
||||
|
||||
template <int I> class placeholder {};
|
||||
|
||||
typedef const lambda_functor<placeholder<FIRST> > placeholder1_type;
|
||||
typedef const lambda_functor<placeholder<SECOND> > placeholder2_type;
|
||||
typedef const lambda_functor<placeholder<THIRD> > placeholder3_type;
|
||||
|
||||
// free variables are lambda_functors. This is to allow uniform handling with
|
||||
// other lambda_functors.
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
|
||||
// Tagged lambda_functor -------------
|
||||
|
||||
@@ -41,7 +41,7 @@ class return_type;
|
||||
template <int I, class Act> class action;
|
||||
|
||||
template <class BinderArgs>
|
||||
class lambda_functor;
|
||||
struct lambda_functor;
|
||||
|
||||
|
||||
template <class Action,
|
||||
|
||||
@@ -514,22 +514,14 @@ public:
|
||||
|
||||
template<class A, class B>
|
||||
struct return_type {
|
||||
private:
|
||||
|
||||
typedef typename detail::remove_reference_and_cv<B>::type plainB;
|
||||
|
||||
typedef typename detail::member_pointer<plainB>::type type0;
|
||||
// we remove the reference now, as we may have to add cv:s
|
||||
typedef typename boost::remove_reference<type0>::type type1;
|
||||
typedef typename detail::member_pointer<plainB>::type type1;
|
||||
|
||||
// A is a reference to pointer
|
||||
// remove the top level cv qualifiers and reference
|
||||
typedef typename
|
||||
detail::remove_reference_and_cv<A>::type non_ref_A;
|
||||
// A is a pointer type
|
||||
typedef typename ::boost::remove_pointer<A>::type non_pointer_A;
|
||||
|
||||
// A is a pointer type, so take the type pointed to
|
||||
typedef typename ::boost::remove_pointer<non_ref_A>::type non_pointer_A;
|
||||
|
||||
public:
|
||||
// For non-reference types, we must add const and/or volatile if
|
||||
// the pointer type has these qualifiers
|
||||
// If the member is a reference, these do not have any effect
|
||||
@@ -544,9 +536,7 @@ public:
|
||||
typename ::boost::add_volatile<type2>::type,
|
||||
type2
|
||||
>::RET type3;
|
||||
// add reference back
|
||||
typedef typename ::boost::add_reference<type3>::type type;
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
@@ -634,10 +624,12 @@ public:
|
||||
|
||||
template<class A, class B>
|
||||
struct return_type_2<other_action<member_pointer_action>, A, B> {
|
||||
private:
|
||||
|
||||
typedef typename
|
||||
detail::remove_reference_and_cv<B>::type plainB;
|
||||
public:
|
||||
typedef typename
|
||||
detail::member_pointer<plainB>::qualified_class_type B_class;
|
||||
|
||||
typedef typename
|
||||
detail::member_pointer_action_helper<
|
||||
detail::member_pointer<plainB>::is_data_member,
|
||||
|
||||
@@ -69,9 +69,9 @@ struct return_type {
|
||||
|
||||
|
||||
// different arities:
|
||||
template <class Act, class A1> struct return_type_1; // 1-ary actions
|
||||
template <class Act, class A1, class A2> struct return_type_2; // 2-ary
|
||||
template <class Act, class Args> struct return_type_N; // >3- ary
|
||||
template <class Act, class A1> class return_type_1; // 1-ary actions
|
||||
template <class Act, class A1, class A2> class return_type_2; // 2-ary
|
||||
template <class Act, class Args> class return_type_N; // >3- ary
|
||||
|
||||
|
||||
// Unary actions (result from unary operators)
|
||||
@@ -140,8 +140,8 @@ typedef typename
|
||||
// We need to make a conservative choise here.
|
||||
// The resulting lambda functor stores all const reference arguments as
|
||||
// const copies. References to non-const are stored as such.
|
||||
// So if the source of the argument is a const open argument, a bound
|
||||
// argument stored as a const reference, or a function returning a
|
||||
// So if the source of the argument is an const open argument, a bound
|
||||
// argument stroed as a const reference, or a function returning a
|
||||
// const reference, that information is lost. There is no way of
|
||||
// telling apart 'real const references' from just 'LL internal
|
||||
// const references' (or it would be really hard)
|
||||
@@ -154,6 +154,24 @@ typedef typename
|
||||
|
||||
template <class Act, class A, class B> struct return_type_2_protect {
|
||||
|
||||
// typedef typename boost::remove_reference<A>::type A1;
|
||||
// typedef typename boost::remove_reference<B>::type B1;
|
||||
|
||||
// // adding const to a function type fails, these tests are to
|
||||
// // avoid that. Note that only the true branch is instantiated with this IF
|
||||
// typedef typename
|
||||
// detail::IF_type<
|
||||
// !is_lambda_functor<A1>::value && (boost::is_function<A1>::value || !(boost::is_const<A1>::value)),
|
||||
// boost::add_reference<A1>,
|
||||
// boost::add_const<A1>
|
||||
// >::type A2;
|
||||
|
||||
// typedef typename
|
||||
// detail::IF_type<
|
||||
// !is_lambda_functor<B1>::value && ( boost::is_function<B1>::value || !(boost::is_const<B1>::value)),
|
||||
// boost::add_reference<B1>,
|
||||
// boost::add_const<B1>
|
||||
// >::type B2;
|
||||
|
||||
|
||||
typedef typename
|
||||
@@ -172,6 +190,17 @@ typedef typename
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
// // unary function action (it is binary action)
|
||||
// // If a function object overloads operator(), the return type could depend
|
||||
// // on the argument types. This is not taken into consideration.
|
||||
// template<class A, class B, class Ret>
|
||||
// struct return_type_2<function_action<2, Ret>, A, B> {
|
||||
// typedef typename return_type_1<function_action<1, Ret>, A>::type type;
|
||||
// };
|
||||
|
||||
|
||||
// reduce to lambda_functor_args
|
||||
// to be on the safe side, constness and references are stripped away,
|
||||
// though the type should always be plain
|
||||
@@ -327,8 +356,8 @@ public:
|
||||
};
|
||||
|
||||
template<class Act, class Args, int Code, class Open>
|
||||
struct return_type<lambda_functor_args<action<2, Act>, Args, Code>, Open> {
|
||||
private:
|
||||
class return_type<lambda_functor_args<action<2, Act>, Args, Code>, Open> {
|
||||
|
||||
typedef typename return_type<
|
||||
typename detail::tuple_element_as_reference<0, Args>::type,
|
||||
Open
|
||||
@@ -358,13 +387,87 @@ public:
|
||||
|
||||
// This is the general case. Will match any action with arity >= 3
|
||||
template<int I, class Act, class Args, int Code, class Open>
|
||||
struct return_type<lambda_functor_args<action<I, Act>, Args, Code>, Open> {
|
||||
private:
|
||||
class return_type<lambda_functor_args<action<I, Act>, Args, Code>, Open> {
|
||||
typedef typename detail::map_to_return_types<Args, Open>::type actual_args;
|
||||
public:
|
||||
typedef typename return_type_N<Act, actual_args>::type type;
|
||||
};
|
||||
|
||||
// template<class Act, class Args, int Code, class Open>
|
||||
// class return_type<lambda_functor_args<action<3, Act>, Args, Code>, Open> {
|
||||
|
||||
// typedef typename return_type<
|
||||
// typename detail::tuple_element_as_reference<0, Args>::type,
|
||||
// Open
|
||||
// >::type A_type;
|
||||
|
||||
// typedef typename return_type<
|
||||
// typename detail::tuple_element_as_reference<1, Args>::type,
|
||||
// Open
|
||||
// >::type B_type;
|
||||
|
||||
// typedef typename return_type<
|
||||
// typename detail::tuple_element_as_reference<2, Args>::type,
|
||||
// Open
|
||||
// >::type C_type;
|
||||
|
||||
// typedef typename boost::add_reference<
|
||||
// typename boost::add_const<A_type>::type
|
||||
// >::type refc_A_type;
|
||||
// typedef typename boost::add_reference<
|
||||
// typename boost::add_const<B_type>::type
|
||||
// >::type refc_B_type;
|
||||
// typedef typename boost::add_reference<
|
||||
// typename boost::add_const<C_type>::type
|
||||
// >::type refc_C_type;
|
||||
|
||||
// public:
|
||||
// // no 3- or higher ary protectable actions exist, no need to check
|
||||
// typedef typename return_type_3<Act, refc_A_type, refc_B_type, refc_C_type>::type type;
|
||||
// };
|
||||
|
||||
// // 4 args or more (must be a function action)
|
||||
// template<int I, class Act, class Args, int Code, class Open>
|
||||
// class return_type<lambda_functor_args<action<I, Act>, Args, Code>, Open> {
|
||||
|
||||
// typedef typename return_type<
|
||||
// typename detail::tuple_element_as_reference<0, Args>::type,
|
||||
// Open
|
||||
// >::type A_type;
|
||||
|
||||
// typedef typename return_type<
|
||||
// typename detail::tuple_element_as_reference<1, Args>::type,
|
||||
// Open
|
||||
// >::type B_type;
|
||||
|
||||
// typedef typename return_type<
|
||||
// typename detail::tuple_element_as_reference<2, Args>::type,
|
||||
// Open
|
||||
// >::type C_type;
|
||||
|
||||
// typedef typename return_type<
|
||||
// typename detail::tuple_element_as_reference<3, Args>::type,
|
||||
// Open
|
||||
// >::type D_type;
|
||||
|
||||
// typedef typename boost::add_reference<
|
||||
// typename boost::add_const<A_type>::type
|
||||
// >::type refc_A_type;
|
||||
// typedef typename boost::add_reference<
|
||||
// typename boost::add_const<B_type>::type
|
||||
// >::type refc_B_type;
|
||||
// typedef typename boost::add_reference<
|
||||
// typename boost::add_const<C_type>::type
|
||||
// >::type refc_C_type;
|
||||
// typedef typename boost::add_reference<
|
||||
// typename boost::add_const<D_type>::type
|
||||
// >::type refc_D_type;
|
||||
|
||||
// public:
|
||||
// typedef typename return_type_4<Act, refc_A_type, refc_B_type, refc_C_type, refc_D_type>::type type;
|
||||
// };
|
||||
|
||||
|
||||
|
||||
// special case for comma action:
|
||||
// As the return type needs to be exactly the type of the rightmost argument,
|
||||
@@ -373,8 +476,8 @@ public:
|
||||
// return_type_2 for user defined types.
|
||||
|
||||
template<class Args, int Code, class Open>
|
||||
struct return_type<lambda_functor_args<action<2, other_action<comma_action> >, Args, Code>, Open> {
|
||||
private:
|
||||
class return_type<lambda_functor_args<action<2, other_action<comma_action> >, Args, Code>, Open> {
|
||||
|
||||
typedef typename return_type<
|
||||
typename detail::tuple_element_as_reference<0, Args>::type,
|
||||
Open
|
||||
@@ -434,6 +537,34 @@ struct return_type<lambda_functor_args<action<4, curry_action<2> >, Args, Code>,
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// // 3 arguments or more ---------------------------------------------
|
||||
// // this must be a function_action. Note that the previous unary and binary
|
||||
// // specalisations take care of nullary and unary function adaptors, that is,
|
||||
// // unary and binary actions.
|
||||
// // Since function_actions determine the return type based on the function
|
||||
// // object only, we can ignore the arguments and reuse return_type_1.
|
||||
|
||||
// template <int I, class Act, class Args, int Code, class Open>
|
||||
// class return_type<lambda_functor_args<action<I, Act>, Args, Code>, Open> {
|
||||
|
||||
// typedef typename return_type<
|
||||
// typename detail::tuple_element_as_reference<0, Args>::type,
|
||||
// Open
|
||||
// >::type A_type;
|
||||
|
||||
// // reference is added, so that specializations for return_type_1
|
||||
// // become easier.
|
||||
// typedef typename boost::add_reference<
|
||||
// typename boost::add_const<A_type>::type
|
||||
// >::type refc_A_type;
|
||||
|
||||
// public:
|
||||
|
||||
// typedef typename return_type_1_protect<Act, refc_A_type>::type type;
|
||||
// };
|
||||
|
||||
// The explicit return type action case, it is unary
|
||||
template<class RET, class Args, int Code, class Open>
|
||||
struct return_type<
|
||||
|
||||
@@ -40,19 +40,19 @@ template <int Code> struct selector {
|
||||
// The cases cover all other placeholders
|
||||
template <> struct selector<NONE> {
|
||||
template<class RET, class Op, class A, class B, class C>
|
||||
static RET select(Op& op, A&, B&, C&) {
|
||||
static RET select(Op& op, A& a, B& b, C& c) {
|
||||
return op.template ret_call<RET>();
|
||||
}
|
||||
};
|
||||
template <> struct selector<FIRST> {
|
||||
template<class RET, class Op, class A, class B, class C>
|
||||
static RET select(Op& op, A& a, B&, C&) {
|
||||
static RET select(Op& op, A& a, B& b, C& c) {
|
||||
return op.template ret_call<RET>(a);
|
||||
}
|
||||
};
|
||||
template <> struct selector<SECOND> {
|
||||
template<class RET, class Op, class A, class B, class C>
|
||||
static RET select(Op& op, A& a, B& b, C&) {
|
||||
static RET select(Op& op, A& a, B& b, C& c) {
|
||||
return op.template ret_call<RET>(a, b);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -291,6 +291,7 @@ public:
|
||||
|
||||
// BOOST_LAMBDA_A_I_LIST(N, X) is a list of form X0, X1, ..., XN
|
||||
// BOOST_LAMBDA_A_I_B_LIST(N, X, Y) is a list of form X0 Y, X1 Y, ..., XN Y
|
||||
// BOOST_LAMBDA_A_I_B_LIST(N, X, Y) is a list of form X0 Y0, X1 Y1, ..., XN YN
|
||||
|
||||
#define BOOST_LAMBDA_A_I(i, A) \
|
||||
BOOST_PP_COMMA_IF(i) BOOST_PP_CAT(A,i)
|
||||
@@ -298,12 +299,19 @@ BOOST_PP_COMMA_IF(i) BOOST_PP_CAT(A,i)
|
||||
#define BOOST_LAMBDA_A_I_B(i, T) \
|
||||
BOOST_PP_COMMA_IF(i) BOOST_PP_CAT(BOOST_PP_TUPLE_ELEM(2,0,T),i) BOOST_PP_TUPLE_ELEM(2,1,T)
|
||||
|
||||
#define BOOST_LAMBDA_A_I_B_I(i, A, B) \
|
||||
BOOST_PP_COMMA_IF(i) \
|
||||
BOOST_PP_CAT(A,i) \
|
||||
BOOST_PP_CAT(B,i)
|
||||
|
||||
#define BOOST_LAMBDA_A_I_LIST(i, A) \
|
||||
BOOST_PP_REPEAT(i,BOOST_LAMBDA_A_I, A)
|
||||
|
||||
#define BOOST_LAMBDA_A_I_B_LIST(i, A, B) \
|
||||
BOOST_PP_REPEAT(i,BOOST_LAMBDA_A_I_B, (A,B))
|
||||
|
||||
//#define BOOST_LAMBDA_A_I_B_I_LIST(i, A, B) \
|
||||
//BOOST_PP_REPEAT(i, BOOST_LAMBDA_A_I_B_I, A)
|
||||
|
||||
// Switch related macros -------------------------------------------
|
||||
#define BOOST_LAMBDA_SWITCH_CASE_BLOCK(N, A) \
|
||||
|
||||
@@ -18,17 +18,15 @@
|
||||
|
||||
#include "boost/lambda/core.hpp"
|
||||
|
||||
#ifdef BOOST_NO_FDECL_TEMPLATES_AS_TEMPLATE_TEMPLATE_PARAMS
|
||||
#include <istream>
|
||||
#include <ostream>
|
||||
#endif
|
||||
|
||||
#include "boost/lambda/detail/operator_actions.hpp"
|
||||
#include "boost/lambda/detail/operator_lambda_functor_base.hpp"
|
||||
#include "boost/lambda/detail/operator_return_type_traits.hpp"
|
||||
|
||||
#ifdef BOOST_NO_FORWARD_DECLARADED_TEMPLATES_AS_TEMPLATE_TEMPLATE_PARAMETERS
|
||||
#include <istream>
|
||||
#include <ostream>
|
||||
#endif
|
||||
|
||||
#include "boost/lambda/detail/operators.hpp"
|
||||
#include "boost/lambda/detail/member_ptr.hpp"
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
BOOST = ../../..
|
||||
|
||||
CXX = gcc3
|
||||
CXX = gcc
|
||||
EXTRAFLAGS = -pedantic -Wno-long-long -ftemplate-depth-50
|
||||
LIBS = -lstdc++
|
||||
|
||||
@@ -23,10 +23,11 @@ AR = ar
|
||||
|
||||
SOURCES = \
|
||||
is_instance_of_test.cpp \
|
||||
operator_tests_simple.cpp \
|
||||
member_pointer_test.cpp \
|
||||
control_structures.cpp \
|
||||
switch_construct.cpp \
|
||||
cast_test.cpp \
|
||||
operator_tests_simple.cpp \
|
||||
bind_tests_simple.cpp \
|
||||
bind_tests_advanced.cpp \
|
||||
bll_and_function.cpp \
|
||||
@@ -34,8 +35,6 @@ constructor_tests.cpp \
|
||||
extending_return_type_traits.cpp \
|
||||
bind_tests_simple_function_references.cpp \
|
||||
exception_test.cpp \
|
||||
cast_test.cpp \
|
||||
phoenix_control_structures_test.cpp \
|
||||
|
||||
|
||||
# Create lists of object files from the source file lists.
|
||||
@@ -78,7 +77,7 @@ run:
|
||||
./bll_and_function.exe
|
||||
./bind_tests_simple_function_references.exe
|
||||
./exception_test.exe
|
||||
./phoenix_control_structures_test.exe
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -3,9 +3,8 @@
|
||||
#define BOOST_INCLUDE_MAIN // for testing, include rather than link
|
||||
#include <boost/test/test_tools.hpp> // see "Header Implementation Option"
|
||||
|
||||
#include "boost/lambda/lambda.hpp"
|
||||
#include "boost/lambda/bind.hpp"
|
||||
|
||||
#include "boost/lambda/lambda.hpp"
|
||||
|
||||
#include "boost/any.hpp"
|
||||
|
||||
@@ -34,8 +33,6 @@ fptr_type sum_or_product(bool x) {
|
||||
// returns a pointer to a binary function.
|
||||
struct which_one {
|
||||
typedef fptr_type (*result_type)(bool x);
|
||||
template <class T> struct sig { typedef result_type type; };
|
||||
|
||||
result_type operator()() const { return sum_or_product; }
|
||||
};
|
||||
|
||||
@@ -89,32 +86,31 @@ int call_with_100(const F& f) {
|
||||
template<class F>
|
||||
int call_with_101(const F& f) {
|
||||
|
||||
return bind(unlambda(f), _1)(make_const(101));
|
||||
return bind(unlambda(ret<int>(f)), _1)(make_const(101));
|
||||
|
||||
// the ret must be inside of unlambda, since unlambda requires its argument
|
||||
// to define result_type.
|
||||
// if F is not a lambda functor ret<int>(f) fails at compile time!
|
||||
}
|
||||
|
||||
|
||||
void test_unlambda() {
|
||||
|
||||
int i = 1;
|
||||
|
||||
BOOST_TEST(unlambda(_1 + _2)(i, i) == 2);
|
||||
BOOST_TEST(unlambda(++var(i))() == 2);
|
||||
BOOST_TEST(call_with_100(_1 + 1) == 101);
|
||||
|
||||
BOOST_TEST(call_with_100(ret<int>(_1 + 1)) == 101);
|
||||
// note, that the functor must define the result_type typedef, as the bind
|
||||
// int the called function does not do that.
|
||||
|
||||
BOOST_TEST(call_with_101(_1 + 1) == 102);
|
||||
// This one leaves the return type to be specified by the bind in the
|
||||
// called function, and that makes things kind of hard in the called
|
||||
// function
|
||||
|
||||
BOOST_TEST(call_with_100(std::bind1st(std::plus<int>(), 1)) == 101);
|
||||
|
||||
BOOST_TEST(call_with_100(bind(std_functor(std::bind1st(std::plus<int>(), 1)), _1)) == 101);
|
||||
|
||||
// std_functor insturcts LL that the functor defines a result_type typedef
|
||||
// rather than a sig template.
|
||||
bind(std_functor(std::plus<int>()), _1, _2)(i, i);
|
||||
// BOOST_TEST(call_with_101(std::bind1st(std::plus<int>(), 1)) == 102);
|
||||
// this would fail, as it would lead to ret being called with other than
|
||||
// a lambda functor
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// protect ------------------------------------------------------------
|
||||
|
||||
// protect protects a lambda functor from argument substitution.
|
||||
@@ -122,14 +118,21 @@ void test_unlambda() {
|
||||
|
||||
namespace ll {
|
||||
|
||||
struct for_each {
|
||||
struct for_each : public has_sig {
|
||||
|
||||
// note, std::for_each returns it's last argument
|
||||
// We want the same behaviour from our ll::for_each.
|
||||
// However, the functor can be called with any arguments, and
|
||||
// the return type thus depends on the argument types.
|
||||
// The basic mechanism (provide a result_type typedef) does not
|
||||
// work.
|
||||
|
||||
// There is an alternative for this kind of situations, which LL
|
||||
// borrows from FC++ (by Yannis Smaragdakis and Brian McNamara).
|
||||
|
||||
// 1. Provide a sig class member template:
|
||||
// If you want to use this mechanism, your function object class needs to
|
||||
// 1. inhertit publicly from has_sig
|
||||
// 2. Provide a sig class member template:
|
||||
|
||||
// The return type deduction system instantiate this class as:
|
||||
// sig<Args>::type, where Args is a boost::tuples::cons-list
|
||||
@@ -145,14 +148,17 @@ struct for_each {
|
||||
// if the functor has several operator()'s, even if they have different
|
||||
// number of arguments.
|
||||
|
||||
// Note, that the argument types in Args are guaranteed to be non-reference
|
||||
// types, but they can have cv-qualifiers.
|
||||
|
||||
template <class Args>
|
||||
// Note, that the argument types in Args can be arbitrary types, particularly
|
||||
// they can be reference types and can have qualifiers or both.
|
||||
// So some care will be needed in this respect.
|
||||
|
||||
template <class Args>
|
||||
struct sig {
|
||||
typedef typename boost::remove_const<
|
||||
typename boost::tuples::element<3, Args>::type
|
||||
>::type type;
|
||||
typename boost::remove_reference<
|
||||
typename boost::tuples::element<3, Args>::type
|
||||
>::type
|
||||
>::type type;
|
||||
};
|
||||
|
||||
template <class A, class B, class C>
|
||||
@@ -199,7 +205,6 @@ void test_protect()
|
||||
);
|
||||
BOOST_TEST(sum == (1+15)*15/2 + 15);
|
||||
|
||||
(1 + protect(_1))(sum);
|
||||
|
||||
int k = 0;
|
||||
((k += constant(1)) += protect(constant(2)))();
|
||||
@@ -227,15 +232,10 @@ void test_protect()
|
||||
// something like this:
|
||||
// (protect(std::cout << _1), bind(ref, std::cout << _1))(i)(j);
|
||||
|
||||
|
||||
// the stuff below works, but we do not want extra output to
|
||||
// cout, must be changed to stringstreams but stringstreams do not
|
||||
// work due to a bug in the type deduction. Will be fixed...
|
||||
#if 0
|
||||
// But for now, ref is not bindable. There are other ways around this:
|
||||
|
||||
int x = 1, y = 2;
|
||||
(protect(std::cout << _1), (std::cout << _1, 0))(x)(y);
|
||||
// int x = 1, y = 2;
|
||||
// (protect(std::cout << _1), (std::cout << _1, 0))(x)(y);
|
||||
|
||||
// added one dummy value to make the argument to comma an int
|
||||
// instead of ostream&
|
||||
@@ -243,10 +243,7 @@ void test_protect()
|
||||
// Note, the same problem is more apparent without protect
|
||||
// (std::cout << 1, std::cout << constant(2))(); // does not work
|
||||
|
||||
(boost::ref(std::cout << 1), std::cout << constant(2))(); // this does
|
||||
|
||||
#endif
|
||||
|
||||
// (boost::ref(std::cout << 1), std::cout << constant(2))(); // this does
|
||||
}
|
||||
|
||||
|
||||
@@ -257,22 +254,17 @@ void test_lambda_functors_as_arguments_to_lambda_functors() {
|
||||
|
||||
// Note however, that the argument/type substitution is not entered again.
|
||||
// This means, that something like this will not work:
|
||||
|
||||
(_1 + _2)(_1, make_const(7));
|
||||
(_1 + _2)(bind(&sum_0), make_const(7));
|
||||
|
||||
(_1 + _2)(bind(&sum_0), make_const(7));
|
||||
// or it does work, but the effect is not to call
|
||||
// sum_0() + 7, but rather
|
||||
// bind(sum_0) + 7, which results in another lambda functor
|
||||
// (lambda functor + int) and can be called again
|
||||
BOOST_TEST((_1 + _2)(bind(&sum_0), make_const(7))() == 7);
|
||||
|
||||
int i = 3, j = 12;
|
||||
BOOST_TEST((_1 - _2)(_2, _1)(i, j) == j - i);
|
||||
|
||||
// also, note that lambda functor are no special case for bind if received
|
||||
// as a parameter. In oder to be bindable, the functor must
|
||||
// defint the sig template, or then
|
||||
// either define the result_type typedef, have the sig template, or then
|
||||
// the return type must be defined within the bind call. Lambda functors
|
||||
// do define the sig template, so if the return type deduction system
|
||||
// covers the case, there is no need to specify the return type
|
||||
@@ -280,19 +272,55 @@ void test_lambda_functors_as_arguments_to_lambda_functors() {
|
||||
|
||||
int a = 5, b = 6;
|
||||
|
||||
// Let type deduction find out the return type
|
||||
BOOST_TEST(bind(_1, _2, _3)(unlambda(_1 + _2), a, b) == 11);
|
||||
// Let type deduction take find out the return type
|
||||
BOOST_TEST(bind(_1, _2, _3)(_1 + _2, a, b) == 11);
|
||||
|
||||
//specify it yourself:
|
||||
BOOST_TEST(bind(_1, _2, _3)(ret<int>(_1 + _2), a, b) == 11);
|
||||
BOOST_TEST(ret<int>(bind(_1, _2, _3))(_1 + _2, a, b) == 11);
|
||||
BOOST_TEST(bind<int>(_1, _2, _3)(_1 + _2, a, b) == 11);
|
||||
|
||||
bind(_1,1.0)(_1+_1);
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
void test_currying() {
|
||||
|
||||
int a = 1, b = 2, c = 3;
|
||||
|
||||
// lambda functors support currying:
|
||||
// binary functor can be called with just one argument, the result is
|
||||
// a unary lambda functor.
|
||||
// 3-ary functor can be called with one or two arguments (and with 3
|
||||
// of course)
|
||||
|
||||
BOOST_TEST((_1 + _2)(a)(b) == 3);
|
||||
|
||||
BOOST_TEST((_1 + _2 + _3)(a, b)(c) == 6);
|
||||
BOOST_TEST((_1 + _2 + _3)(a)(b, c) == 6);
|
||||
BOOST_TEST((_1 + _2 + _3)(a)(b)(c) == 6);
|
||||
|
||||
// Also, lambda functors passed as arguments end up being curryable
|
||||
|
||||
BOOST_TEST(bind(_1, _2, _3)(_1 + _2 + _3, a, b)(c) == 6);
|
||||
BOOST_TEST(bind(_1, _2)(_1 + _2 + _3, a)(b, c) == 6);
|
||||
BOOST_TEST(bind(_1, _2)(_1 + _2 + _3, a)(b)(c) == 6);
|
||||
|
||||
bind(_1, _2)(_1 += (_2 + _3), a)(b)(c);
|
||||
BOOST_TEST(a == 6);
|
||||
|
||||
bind(_1, _2)(a += (_1 + _2 + _3), c)(c)(c);
|
||||
BOOST_TEST(a == 6+3*c);
|
||||
|
||||
a = 1, b = 2, c = 3;
|
||||
// and protecting should work as well
|
||||
BOOST_TEST(bind(_1, _2)(_1 + _2 + _3 + protect(_1), a)(b)(c)(a) == 7);
|
||||
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
void test_const_parameters() {
|
||||
|
||||
@@ -329,6 +357,7 @@ int test_main(int, char *[]) {
|
||||
test_unlambda();
|
||||
test_protect();
|
||||
test_lambda_functors_as_arguments_to_lambda_functors();
|
||||
test_currying();
|
||||
test_const_parameters();
|
||||
test_break_const();
|
||||
return 0;
|
||||
|
||||
@@ -39,13 +39,10 @@ void test_member_functions()
|
||||
A a(10);
|
||||
int i = 1;
|
||||
|
||||
|
||||
|
||||
|
||||
BOOST_TEST(bind(&A::add, ref(a), _1)(i) == 11);
|
||||
BOOST_TEST(bind(&A::add, &a, _1)(i) == 11);
|
||||
BOOST_TEST(bind(&A::add, _1, 1)(a) == 11);
|
||||
BOOST_TEST(bind(&A::add, _1, 1)(make_const(&a)) == 11);
|
||||
BOOST_TEST(bind(&A::add, ref(a), _1)(i) == 11);
|
||||
BOOST_TEST(bind(&A::add, &a, _1)(i) == 11);
|
||||
BOOST_TEST(bind(&A::add, _1, 1)(a) == 11);
|
||||
BOOST_TEST(bind(&A::add, _1, 1)(make_const(&a)) == 11);
|
||||
|
||||
// This should fail, as lambda functors store arguments as const
|
||||
// bind(&A::add, a, _1);
|
||||
|
||||
@@ -22,12 +22,16 @@ using namespace std;
|
||||
void test_function() {
|
||||
|
||||
boost::function<int, int, int> f;
|
||||
f = _1 + _2;
|
||||
f = unlambda(_1 + _2);
|
||||
|
||||
// unlambda must be used, because boost::function tries to take the
|
||||
// address of the function object that is assigned. However, the
|
||||
// operator& is overloaded for lambda functors, which creates a conflict
|
||||
|
||||
BOOST_TEST(f(1, 2)== 3);
|
||||
|
||||
int i=1; int j=2;
|
||||
boost::function<int&, int&, int> g = _1 += _2;
|
||||
boost::function<int&, int&, int> g = unlambda(_1 += _2);
|
||||
g(i, j);
|
||||
BOOST_TEST(i==3);
|
||||
|
||||
@@ -35,7 +39,7 @@ void test_function() {
|
||||
|
||||
int* sum = new int();
|
||||
*sum = 0;
|
||||
boost::function<int&, int> counter = *sum += _1;
|
||||
boost::function<int&, int> counter = unlambda(*sum += _1);
|
||||
counter(5); // ok, sum* = 5;
|
||||
BOOST_TEST(*sum == 5);
|
||||
delete sum;
|
||||
|
||||
@@ -2,8 +2,7 @@
|
||||
#include <boost/test/test_tools.hpp> // see "Header Implementation Option"
|
||||
|
||||
#include "boost/lambda/lambda.hpp"
|
||||
#include "boost/lambda/if.hpp"
|
||||
#include "boost/lambda/loops.hpp"
|
||||
#include "boost/lambda/control_structures.hpp"
|
||||
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
|
||||
@@ -33,11 +33,11 @@ void erroneous_exception_related_lambda_expressions() {
|
||||
// this should fail too for the same reason
|
||||
// try_catch(rethrow(), catch_all(cout << constant("Howdy")))();
|
||||
|
||||
// this fails too (_e outside of catch_exception)
|
||||
// (_1 + _2 + _e)(i, i, i);
|
||||
// this fails too (_E outside of catch_exception)
|
||||
// (_1 + _2 + _E)(i, i, i);
|
||||
|
||||
// and this (_e outside of catch_exception)
|
||||
// try_catch( throw_exception(1), catch_all(cout << _e));
|
||||
// and this (_E outside of catch_exception)
|
||||
// try_catch( throw_exception(1), catch_all(cout << _E));
|
||||
|
||||
// and this (_3 in catch_exception
|
||||
// try_catch( throw_exception(1), catch_exception<int>(cout << _3));
|
||||
@@ -531,7 +531,7 @@ void return_type_matching() {
|
||||
try_catch(
|
||||
_1 + 1,
|
||||
catch_exception<int>((&_1, rethrow())), // no match, but ok since throws
|
||||
catch_exception<char>(_e) // ok, char convertible to int
|
||||
catch_exception<char>(_E) // ok, char convertible to int
|
||||
)(i)
|
||||
|
||||
== 2
|
||||
@@ -542,19 +542,19 @@ void return_type_matching() {
|
||||
|
||||
// try_catch(
|
||||
// _1 += 1,
|
||||
// catch_exception<char>(_e) // NOT ok, char not convertible to int&
|
||||
// catch_exception<char>(_E) // NOT ok, char not convertible to int&
|
||||
// )(i);
|
||||
|
||||
// if you don't care about the return type, you can use make_void
|
||||
try_catch(
|
||||
make_void(_1 += 1),
|
||||
catch_exception<char>(_e) // since try is void, catch can return anything
|
||||
catch_exception<char>(_E) // since try is void, catch can return anything
|
||||
)(i);
|
||||
BOOST_TEST(i == 2);
|
||||
|
||||
try_catch(
|
||||
(_1 += 1, throw_exception('a')),
|
||||
catch_exception<char>(_e) // since try throws, it is void,
|
||||
catch_exception<char>(_E) // since try throws, it is void,
|
||||
// so catch can return anything
|
||||
)(i);
|
||||
BOOST_TEST(i == 3);
|
||||
@@ -565,7 +565,7 @@ void return_type_matching() {
|
||||
throw_exception(1),
|
||||
catch_exception<int>(throw_exception('b'))
|
||||
),
|
||||
catch_exception<char>( _1 = _e )
|
||||
catch_exception<char>( _1 = _E )
|
||||
)(a);
|
||||
BOOST_TEST(a == 'b');
|
||||
}
|
||||
@@ -593,3 +593,46 @@ int test_main(int, char *[]) {
|
||||
|
||||
|
||||
|
||||
// cout << "Before make void call. i ="<< i << "\n";
|
||||
// (make_void(free1 += 3))(i);
|
||||
// cout << "After make void call, should be += 3 i = " << i << "\n";
|
||||
|
||||
// int j =0;
|
||||
// var_type<int>::type vj(var(j));
|
||||
// (make_void(for_loop(vj = 0, vj < free1, ++vj, cout << vj << "\n")))(i);
|
||||
|
||||
// try_catch( make_void(free1 += 3 + free2),
|
||||
// catch_exception<int>( cout << constant("Should work: ") << free1 + free2 << "\n" )
|
||||
// )
|
||||
// (i, i);
|
||||
|
||||
// try_catch( make_void(free1 += 3),
|
||||
// catch_exception<int>( cout << constant("Should work: ") << free1 + free2 << "\n" )
|
||||
// )
|
||||
// (i, i);
|
||||
|
||||
// try_catch( throw_exception(1),
|
||||
// catch_exception<int>(
|
||||
// throw_exception(2) )
|
||||
// )
|
||||
// ();
|
||||
|
||||
// try_catch( throw_exception(1),
|
||||
// catch_exception<int>(
|
||||
// ((cout << constant("caught int: ") << free1 + free2 << "\n")
|
||||
// ,throw_exception(2) )
|
||||
// ),
|
||||
// catch_all(
|
||||
// ((cout << constant("catch all: ") << free1 + free2 << "\n")
|
||||
// ,rethrow())
|
||||
// )
|
||||
// )(i,i);
|
||||
|
||||
// // try_catch which returns (10 is added, so that the try return type is int
|
||||
// cout << "\n -------------- \n" <<
|
||||
// try_catch( (throw_exception(5), 10),
|
||||
// catch_exception<int>( free1 + free2 + freeE ) // returns int
|
||||
// )
|
||||
// (i, i) << "\n";
|
||||
|
||||
|
||||
|
||||
@@ -188,19 +188,19 @@ struct plain_return_type_2<arithmetic_action<multiply_action>, X, Y> {
|
||||
// if you want to make a distinction between differently cv-qualified
|
||||
// types, you need to specialize on a different level:
|
||||
template<>
|
||||
struct return_type_2<arithmetic_action<multiply_action>, XX, YY> {
|
||||
struct return_type_2<arithmetic_action<multiply_action>, XX&, YY&> {
|
||||
typedef YY type;
|
||||
};
|
||||
template<>
|
||||
struct return_type_2<arithmetic_action<multiply_action>, const XX, const YY> {
|
||||
struct return_type_2<arithmetic_action<multiply_action>, const XX&, const YY&> {
|
||||
typedef ZZ type;
|
||||
};
|
||||
template<>
|
||||
struct return_type_2<arithmetic_action<multiply_action>, volatile XX, volatile YY> {
|
||||
struct return_type_2<arithmetic_action<multiply_action>, volatile XX&, volatile YY&> {
|
||||
typedef XX type;
|
||||
};
|
||||
template<>
|
||||
struct return_type_2<arithmetic_action<multiply_action>, volatile const XX, const volatile YY> {
|
||||
struct return_type_2<arithmetic_action<multiply_action>, volatile const XX&, const volatile YY&> {
|
||||
typedef VV type;
|
||||
};
|
||||
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
#include "boost/lambda/lambda.hpp"
|
||||
#include "boost/lambda/bind.hpp"
|
||||
|
||||
#include "boost/lambda/detail/member_ptr.hpp"
|
||||
|
||||
#include <string>
|
||||
|
||||
using namespace boost::lambda;
|
||||
@@ -117,33 +119,30 @@ bool operator->*(B b, A a) {
|
||||
|
||||
// let's provide specializations to take care of the return type deduction.
|
||||
// Note, that you need to provide all four cases for non-const and const
|
||||
// or use the plain_return_type_2 template.
|
||||
// references :(
|
||||
namespace boost {
|
||||
namespace lambda {
|
||||
|
||||
template <>
|
||||
struct return_type_2<other_action<member_pointer_action>, B, A> {
|
||||
struct return_type_2<other_action<member_pointer_action>, B&, A&> {
|
||||
typedef bool type;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct return_type_2<other_action<member_pointer_action>, const B, A> {
|
||||
struct return_type_2<other_action<member_pointer_action>, const B&, A&> {
|
||||
typedef bool type;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct return_type_2<other_action<member_pointer_action>, B, const A> {
|
||||
struct return_type_2<other_action<member_pointer_action>, B&, const A&> {
|
||||
typedef bool type;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct return_type_2<other_action<member_pointer_action>, const B, const A> {
|
||||
struct return_type_2<other_action<member_pointer_action>, const B&, const A&> {
|
||||
typedef bool type;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
} // lambda
|
||||
} // boost
|
||||
|
||||
|
||||
@@ -10,13 +10,6 @@
|
||||
#include <set>
|
||||
#include <string>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
|
||||
#include <sstream>
|
||||
|
||||
using namespace std;
|
||||
using namespace boost;
|
||||
|
||||
using namespace boost::lambda;
|
||||
|
||||
@@ -24,42 +17,6 @@ using namespace boost::lambda;
|
||||
class unary_plus_tester {};
|
||||
unary_plus_tester operator+(const unary_plus_tester& a) { return a; }
|
||||
|
||||
void cout_tests()
|
||||
{
|
||||
// standard ostream and istream operators work
|
||||
// stringstreams etc. do not work:
|
||||
|
||||
// ostringstream os;
|
||||
// os << 1
|
||||
|
||||
// This should the derived basic_ostream instance (or a reference to it)
|
||||
// but now the type deduction returns a reference to ostringstream.
|
||||
// must be fixed.
|
||||
using std::cout;
|
||||
ostringstream os;
|
||||
int i = 10;
|
||||
ret<std::ostream&>(os << _1)(i);
|
||||
|
||||
ret<std::ostream&>(os << constant("FOO"))();
|
||||
|
||||
BOOST_TEST(os.str() == std::string("10FOO"));
|
||||
|
||||
|
||||
// test for constant, constant_ref and var
|
||||
i = 5;
|
||||
constant_type<int>::type ci(constant(i));
|
||||
var_type<int>::type vi(var(i));
|
||||
|
||||
(vi = _1)(make_const(100));
|
||||
BOOST_TEST((ci)() == 5);
|
||||
BOOST_TEST(i == 100);
|
||||
|
||||
int a;
|
||||
constant_ref_type<int>::type cr(constant_ref(i));
|
||||
(++vi, var(a) = cr)();
|
||||
BOOST_TEST(i == 101);
|
||||
}
|
||||
|
||||
void arithmetic_operators() {
|
||||
int i = 1; int j = 2; int k = 3;
|
||||
|
||||
@@ -373,7 +330,7 @@ int test_main(int, char *[]) {
|
||||
address_of_and_dereference();
|
||||
comma();
|
||||
pointer_arithmetic();
|
||||
cout_tests();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,139 +0,0 @@
|
||||
// phoenix_style_control_structures.cpp --------------------------------
|
||||
|
||||
#define BOOST_INCLUDE_MAIN // for testing, include rather than link
|
||||
#include <boost/test/test_tools.hpp> // see "Header Implementation Option"
|
||||
|
||||
#include "boost/lambda/lambda.hpp"
|
||||
#include "boost/lambda/if.hpp"
|
||||
#include "boost/lambda/loops.hpp"
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <cassert>
|
||||
#include <functional>
|
||||
|
||||
|
||||
|
||||
using namespace boost::lambda;
|
||||
using namespace std;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// If-else, while, do-while, for tatements
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int test_main(int, char *[]) {
|
||||
|
||||
vector<int> v;
|
||||
v.clear();
|
||||
v.push_back(1);
|
||||
v.push_back(2);
|
||||
v.push_back(3);
|
||||
v.push_back(4);
|
||||
v.push_back(5);
|
||||
v.push_back(6);
|
||||
v.push_back(7);
|
||||
v.push_back(8);
|
||||
v.push_back(9);
|
||||
v.push_back(10);
|
||||
|
||||
int sum = 0;
|
||||
//////////////////////////////////
|
||||
for_each(v.begin(), v.end(),
|
||||
if_(_1 > 3 && _1 <= 8)
|
||||
[
|
||||
sum += _1
|
||||
]
|
||||
);
|
||||
|
||||
BOOST_TEST(sum == 4+5+6+7+8);
|
||||
|
||||
int gt = 0, eq = 0, lt = 0;
|
||||
//////////////////////////////////
|
||||
for_each(v.begin(), v.end(),
|
||||
if_(_1 > 5)
|
||||
[
|
||||
++var(gt)
|
||||
]
|
||||
.else_
|
||||
[
|
||||
if_(_1 == 5)
|
||||
[
|
||||
++var(eq)
|
||||
]
|
||||
.else_
|
||||
[
|
||||
++var(lt)
|
||||
]
|
||||
]
|
||||
);
|
||||
|
||||
BOOST_TEST(lt==4);
|
||||
BOOST_TEST(eq==1);
|
||||
BOOST_TEST(gt==5);
|
||||
|
||||
vector<int> t = v;
|
||||
|
||||
int counta = 0;
|
||||
int countb = 0;
|
||||
//////////////////////////////////
|
||||
for_each(v.begin(), v.end(),
|
||||
(
|
||||
while_(_1--)
|
||||
[
|
||||
++var(counta)
|
||||
],
|
||||
++var(countb)
|
||||
)
|
||||
);
|
||||
|
||||
BOOST_TEST(counta == 55);
|
||||
BOOST_TEST(countb == 10);
|
||||
|
||||
|
||||
v = t;
|
||||
|
||||
counta = 0; countb = 0;
|
||||
//////////////////////////////////
|
||||
for_each(v.begin(), v.end(),
|
||||
(
|
||||
do_
|
||||
[
|
||||
++var(counta)
|
||||
]
|
||||
.while_(_1--),
|
||||
++var(countb)
|
||||
)
|
||||
);
|
||||
|
||||
BOOST_TEST(counta == (2+11)*10/2);
|
||||
BOOST_TEST(countb == 10);
|
||||
|
||||
|
||||
v = t;
|
||||
counta = 0; countb = 0;
|
||||
//////////////////////////////////
|
||||
int iii;
|
||||
for_each(v.begin(), v.end(),
|
||||
(
|
||||
for_(var(iii) = 0, var(iii) < _1, ++var(iii))
|
||||
[
|
||||
++var(counta)
|
||||
],
|
||||
++var(countb)
|
||||
)
|
||||
);
|
||||
|
||||
BOOST_TEST(counta == (1+10)*10/2);
|
||||
BOOST_TEST(countb == 10);
|
||||
|
||||
v = t;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -5,8 +5,7 @@
|
||||
|
||||
|
||||
#include "boost/lambda/lambda.hpp"
|
||||
#include "boost/lambda/if.hpp"
|
||||
#include "boost/lambda/switch.hpp"
|
||||
#include "boost/lambda/control_structures.hpp"
|
||||
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
|
||||
Reference in New Issue
Block a user