2
0
mirror of https://github.com/boostorg/lambda.git synced 2026-01-21 04:52:25 +00:00

Compare commits

..

27 Commits

Author SHA1 Message Date
Jaakko Järvi
8d46420cf3 adding tests for phoenix style control constructs
[SVN r13537]
2002-04-19 19:46:41 +00:00
Jaakko Järvi
cbe0189caa include file changes
[SVN r13535]
2002-04-19 19:44:43 +00:00
Jaakko Järvi
cd4f8c008d addedd var, constant, constant_ref tests, and cout << _1 etc. tests
[SVN r13534]
2002-04-19 19:44:05 +00:00
Jaakko Järvi
e8def54ef0 changes in include files
[SVN r13533]
2002-04-19 19:43:08 +00:00
Jaakko Järvi
52ef1b9bac some changes in the return_type_2 traits
[SVN r13532]
2002-04-19 19:42:05 +00:00
Jaakko Järvi
f83f913fd7 changed _E to _e (_E is a reserved identifier name)
[SVN r13531]
2002-04-19 19:40:39 +00:00
Jaakko Järvi
39eda970d5 no need to use unlambda anymore
[SVN r13530]
2002-04-19 19:39:44 +00:00
Jaakko Järvi
03f92e2081 no comment
[SVN r13529]
2002-04-19 19:38:55 +00:00
Jaakko Järvi
521b1be1ac changes after making sig template the default
[SVN r13528]
2002-04-19 19:38:12 +00:00
Jaakko Järvi
cf577450e8 added a few tests
[SVN r13527]
2002-04-19 19:34:59 +00:00
Jaakko Järvi
f6708ffe6b fixed a bug in transform return type deductions
[SVN r13299]
2002-03-28 19:19:53 +00:00
Jaakko Järvi
808b2dd7f0 removed a duplicate line
[SVN r13298]
2002-03-28 18:29:44 +00:00
Jaakko Järvi
eac09d219b added default consturctors to placeholders (back)
[SVN r13238]
2002-03-21 22:45:48 +00:00
Jaakko Järvi
1879db42b6 forced KCC to include istrem/ostream since there is a bug
if only iosfwd is included


[SVN r13237]
2002-03-21 16:36:20 +00:00
Jaakko Järvi
fe183e216f removed old commented out code
[SVN r13236]
2002-03-21 16:34:57 +00:00
Jaakko Järvi
2c407cf775 fixed bug in return type deduction
[SVN r13235]
2002-03-21 16:34:02 +00:00
Jaakko Järvi
032b82de7d added function call operators for placeholder
[SVN r13234]
2002-03-21 03:55:06 +00:00
Jaakko Järvi
ff2c6018a3 added initializers for placeholder constants
[SVN r13233]
2002-03-21 03:52:09 +00:00
Jaakko Järvi
a9276b49ec removed one unneeded include
[SVN r13228]
2002-03-19 18:19:04 +00:00
Peter Dimov
5211282185 MSVC 7.01a fix.
[SVN r13219]
2002-03-18 18:23:51 +00:00
Jaakko Järvi
9ae841ecf2 removed parameter names (just the types are left) to
prevent unused parameter warnings with some compilers


[SVN r13218]
2002-03-18 17:01:19 +00:00
Jaakko Järvi
8cdf08bc6c removed code that was already commented away
[SVN r13193]
2002-03-14 16:02:32 +00:00
Jaakko Järvi
f96e5a404c changed lambda functor from struct to class, so it's similarly
defined and declared


[SVN r13133]
2002-03-08 14:29:48 +00:00
Jaakko Järvi
145cc3e7e8 include member_ptr.hpp by default as well
[SVN r13132]
2002-03-08 14:27:12 +00:00
Jaakko Järvi
57d827ad82 changed action from struct to class so they're similarly declared and defined
[SVN r13131]
2002-03-08 14:26:29 +00:00
Jaakko Järvi
5fbbc843dd removed some macro defs that were not used
[SVN r13130]
2002-03-08 14:22:14 +00:00
nobody
da31648a61 This commit was manufactured by cvs2svn to create branch
'lambda_development_during_review'.

[SVN r12907]
2002-02-22 21:13:30 +00:00
22 changed files with 395 additions and 350 deletions

View File

@@ -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 - 1,
boost::tuples::length<Args>::value - 2,
Args
>::type
>::type

View File

@@ -54,9 +54,10 @@ namespace lambda {
namespace {
boost::lambda::placeholder1_type free1;
boost::lambda::placeholder2_type free2;
boost::lambda::placeholder3_type free3;
// 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& _1 = free1;
boost::lambda::placeholder2_type& _2 = free2;

View File

@@ -23,7 +23,7 @@ namespace lambda {
template<int Arity, class Act> struct action;
template<int Arity, class Act> class action;
// these need to be defined here, since the corresponding lambda
// functions are members of lambda_functor classes

View File

@@ -30,9 +30,9 @@
#endif // __GNUC__
# if defined __KCC
#if defined __KCC
#define BOOST_NO_FORWARD_DECLARADED_TEMPLATES_AS_TEMPLATE_TEMPLATE_PARAMETERS
#define BOOST_NO_FDECL_TEMPLATES_AS_TEMPLATE_TEMPLATE_PARAMS
#endif // __KCC

View File

@@ -36,6 +36,9 @@ 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
@@ -81,20 +84,88 @@ 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() {}
// 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<FIRST> > {
public:
lambda_functor() {}
template <class A>
A& operator()(A& a) const { return a; }
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
@@ -543,17 +614,6 @@ 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 -------------

View File

@@ -41,7 +41,7 @@ class return_type;
template <int I, class Act> class action;
template <class BinderArgs>
struct lambda_functor;
class lambda_functor;
template <class Action,

View File

@@ -514,14 +514,22 @@ 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 type1;
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;
// A is a pointer type
typedef typename ::boost::remove_pointer<A>::type non_pointer_A;
// 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, 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
@@ -536,7 +544,9 @@ public:
typename ::boost::add_volatile<type2>::type,
type2
>::RET type3;
// add reference back
typedef typename ::boost::add_reference<type3>::type type;
};
};
@@ -624,12 +634,10 @@ 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;
typedef typename
detail::member_pointer<plainB>::qualified_class_type B_class;
public:
typedef typename
detail::member_pointer_action_helper<
detail::member_pointer<plainB>::is_data_member,

View File

@@ -69,9 +69,9 @@ struct return_type {
// different arities:
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
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
// 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 an const open argument, a bound
// argument stroed as a const reference, or a function returning a
// 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
// 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,24 +154,6 @@ 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
@@ -190,17 +172,6 @@ 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
@@ -356,8 +327,8 @@ public:
};
template<class Act, class Args, int Code, class Open>
class return_type<lambda_functor_args<action<2, Act>, Args, Code>, Open> {
struct return_type<lambda_functor_args<action<2, Act>, Args, Code>, Open> {
private:
typedef typename return_type<
typename detail::tuple_element_as_reference<0, Args>::type,
Open
@@ -387,87 +358,13 @@ public:
// This is the general case. Will match any action with arity >= 3
template<int I, class Act, class Args, int Code, class Open>
class return_type<lambda_functor_args<action<I, Act>, Args, Code>, Open> {
struct return_type<lambda_functor_args<action<I, Act>, Args, Code>, Open> {
private:
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,
@@ -476,8 +373,8 @@ public:
// return_type_2 for user defined types.
template<class Args, int Code, class Open>
class return_type<lambda_functor_args<action<2, other_action<comma_action> >, Args, Code>, Open> {
struct return_type<lambda_functor_args<action<2, other_action<comma_action> >, Args, Code>, Open> {
private:
typedef typename return_type<
typename detail::tuple_element_as_reference<0, Args>::type,
Open
@@ -537,34 +434,6 @@ 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<

View File

@@ -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& a, B& b, C& c) {
static RET select(Op& op, A&, B&, 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& b, C& c) {
static RET select(Op& op, A& a, B&, 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& c) {
static RET select(Op& op, A& a, B& b, C&) {
return op.template ret_call<RET>(a, b);
}
};

View File

@@ -291,7 +291,6 @@ 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)
@@ -299,19 +298,12 @@ 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) \

View File

@@ -18,15 +18,17 @@
#include "boost/lambda/core.hpp"
#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
#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"
#include "boost/lambda/detail/operators.hpp"
#include "boost/lambda/detail/member_ptr.hpp"
#endif

View File

@@ -1,6 +1,6 @@
BOOST = ../../..
CXX = gcc
CXX = gcc3
EXTRAFLAGS = -pedantic -Wno-long-long -ftemplate-depth-50
LIBS = -lstdc++
@@ -23,11 +23,10 @@ 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 \
@@ -35,6 +34,8 @@ 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.
@@ -77,7 +78,7 @@ run:
./bll_and_function.exe
./bind_tests_simple_function_references.exe
./exception_test.exe
./phoenix_control_structures_test.exe

View File

@@ -3,8 +3,9 @@
#define BOOST_INCLUDE_MAIN // for testing, include rather than link
#include <boost/test/test_tools.hpp> // see "Header Implementation Option"
#include "boost/lambda/bind.hpp"
#include "boost/lambda/lambda.hpp"
#include "boost/lambda/bind.hpp"
#include "boost/any.hpp"
@@ -33,6 +34,8 @@ 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; }
};
@@ -86,31 +89,32 @@ int call_with_100(const F& f) {
template<class F>
int call_with_101(const F& f) {
return bind(unlambda(ret<int>(f)), _1)(make_const(101));
return bind(unlambda(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() {
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.
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_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_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
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);
}
// protect ------------------------------------------------------------
// protect protects a lambda functor from argument substitution.
@@ -118,21 +122,14 @@ void test_unlambda() {
namespace ll {
struct for_each : public has_sig {
struct for_each {
// 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).
// 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:
// 1. 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
@@ -148,17 +145,14 @@ struct for_each : public has_sig {
// if the functor has several operator()'s, even if they have different
// number of arguments.
// 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>
// Note, that the argument types in Args are guaranteed to be non-reference
// types, but they can have cv-qualifiers.
template <class Args>
struct sig {
typedef typename boost::remove_const<
typename boost::remove_reference<
typename boost::tuples::element<3, Args>::type
>::type
>::type type;
typename boost::tuples::element<3, Args>::type
>::type type;
};
template <class A, class B, class C>
@@ -205,6 +199,7 @@ void test_protect()
);
BOOST_TEST(sum == (1+15)*15/2 + 15);
(1 + protect(_1))(sum);
int k = 0;
((k += constant(1)) += protect(constant(2)))();
@@ -232,10 +227,15 @@ 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,7 +243,10 @@ 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
(boost::ref(std::cout << 1), std::cout << constant(2))(); // this does
#endif
}
@@ -254,17 +257,22 @@ 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)(bind(&sum_0), make_const(7));
(_1 + _2)(_1, 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
// either define the result_type typedef, have the sig template, or then
// defint 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
@@ -272,55 +280,19 @@ void test_lambda_functors_as_arguments_to_lambda_functors() {
int a = 5, b = 6;
// Let type deduction take find out the return type
BOOST_TEST(bind(_1, _2, _3)(_1 + _2, a, b) == 11);
// Let type deduction find out the return type
BOOST_TEST(bind(_1, _2, _3)(unlambda(_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() {
@@ -357,7 +329,6 @@ 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;

View File

@@ -39,10 +39,13 @@ 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);

View File

@@ -22,16 +22,12 @@ using namespace std;
void test_function() {
boost::function<int, int, int> f;
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
f = _1 + _2;
BOOST_TEST(f(1, 2)== 3);
int i=1; int j=2;
boost::function<int&, int&, int> g = unlambda(_1 += _2);
boost::function<int&, int&, int> g = _1 += _2;
g(i, j);
BOOST_TEST(i==3);
@@ -39,7 +35,7 @@ void test_function() {
int* sum = new int();
*sum = 0;
boost::function<int&, int> counter = unlambda(*sum += _1);
boost::function<int&, int> counter = *sum += _1;
counter(5); // ok, sum* = 5;
BOOST_TEST(*sum == 5);
delete sum;

View File

@@ -2,7 +2,8 @@
#include <boost/test/test_tools.hpp> // see "Header Implementation Option"
#include "boost/lambda/lambda.hpp"
#include "boost/lambda/control_structures.hpp"
#include "boost/lambda/if.hpp"
#include "boost/lambda/loops.hpp"
#include <iostream>
#include <algorithm>

View File

@@ -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,46 +593,3 @@ 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";

View File

@@ -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;
};

View File

@@ -7,8 +7,6 @@
#include "boost/lambda/lambda.hpp"
#include "boost/lambda/bind.hpp"
#include "boost/lambda/detail/member_ptr.hpp"
#include <string>
using namespace boost::lambda;
@@ -119,30 +117,33 @@ 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
// references :(
// or use the plain_return_type_2 template.
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

View File

@@ -10,6 +10,13 @@
#include <set>
#include <string>
#include <iostream>
#include <sstream>
using namespace std;
using namespace boost;
using namespace boost::lambda;
@@ -17,6 +24,42 @@ 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;
@@ -330,7 +373,7 @@ int test_main(int, char *[]) {
address_of_and_dereference();
comma();
pointer_arithmetic();
cout_tests();
return 0;
}

View File

@@ -0,0 +1,139 @@
// 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;
}

View File

@@ -5,7 +5,8 @@
#include "boost/lambda/lambda.hpp"
#include "boost/lambda/control_structures.hpp"
#include "boost/lambda/if.hpp"
#include "boost/lambda/switch.hpp"
#include <iostream>
#include <algorithm>