diff --git a/include/boost/lambda/casts.hpp b/include/boost/lambda/casts.hpp index 29437a8..8b3d3a7 100644 --- a/include/boost/lambda/casts.hpp +++ b/include/boost/lambda/casts.hpp @@ -15,12 +15,16 @@ #define BOOST_LAMBDA_CASTS_HPP #include "boost/lambda/detail/suppress_unused.hpp" +#include "boost/lambda/core.hpp" #include namespace boost { namespace lambda { +template +struct return_type_N; + template class cast_action; template class static_cast_action; diff --git a/include/boost/lambda/closures.hpp b/include/boost/lambda/closures.hpp index a6a2b07..f09c8a5 100644 --- a/include/boost/lambda/closures.hpp +++ b/include/boost/lambda/closures.hpp @@ -251,7 +251,7 @@ private: closure& operator=(closure const&); // no assign template - friend struct closure_member; + friend class closure_member; template friend class closure_frame; diff --git a/include/boost/lambda/construct.hpp b/include/boost/lambda/construct.hpp index f6e5e05..06da171 100644 --- a/include/boost/lambda/construct.hpp +++ b/include/boost/lambda/construct.hpp @@ -14,6 +14,9 @@ #if !defined(BOOST_LAMBDA_CONSTRUCT_HPP) #define BOOST_LAMBDA_CONSTRUCT_HPP +#include "boost/type_traits/remove_cv.hpp" +#include "boost/type_traits/is_pointer.hpp" + namespace boost { namespace lambda { diff --git a/include/boost/lambda/control_structures.hpp b/include/boost/lambda/control_structures.hpp index 4164104..74cb97c 100644 --- a/include/boost/lambda/control_structures.hpp +++ b/include/boost/lambda/control_structures.hpp @@ -17,6 +17,7 @@ #include "boost/lambda/detail/operator_actions.hpp" #include "boost/lambda/detail/operator_return_type_traits.hpp" -#include "boost/lambda/detail/control_structures_impl.hpp" +#include "boost/lambda/if.hpp" +#include "boost/lambda/loops.hpp" #endif diff --git a/include/boost/lambda/detail/control_structures_impl.hpp b/include/boost/lambda/detail/control_structures_impl.hpp deleted file mode 100644 index 56f80ac..0000000 --- a/include/boost/lambda/detail/control_structures_impl.hpp +++ /dev/null @@ -1,550 +0,0 @@ -// Boost Lambda Library -- control_structures_impl.hpp --------------------- - -// Copyright (C) 1999, 2000 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi) -// Copyright (C) 2000 Gary Powell (powellg@amazon.com) -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// For more information, see www.boost.org - -// -------------------------------------------------------------------------- - -#if !defined(BOOST_LAMBDA_CONTROL_CONSTRUCTS_HPP) -#define BOOST_LAMBDA_CONTROL_CONSTRUCTS_HPP - -namespace boost { -namespace lambda { - -// -- void return control actions ---------------------- - -class forloop_action {}; -class forloop_no_body_action {}; -class ifthen_action {}; -class ifthenelse_action {}; -class whileloop_action {}; -class whileloop_no_body_action {}; -class dowhileloop_action {}; -class dowhileloop_no_body_action {}; -// -- nonvoid return control actions ---------------------- - -class ifthenelsereturn_action {}; - -// For loop -template -inline const -lambda_functor< - lambda_functor_base< - forloop_action, - tuple, lambda_functor, - lambda_functor, lambda_functor > - > -> -for_loop(const lambda_functor& a1, const lambda_functor& a2, - const lambda_functor& a3, const lambda_functor& a4) { - return - lambda_functor_base< - forloop_action, - tuple, lambda_functor, - lambda_functor, lambda_functor > - > - ( tuple, lambda_functor, - lambda_functor, lambda_functor >(a1, a2, a3, a4) - ); -} - -// No body case. -template -inline const -lambda_functor< - lambda_functor_base< - forloop_no_body_action, - tuple, lambda_functor, lambda_functor > - > -> -for_loop(const lambda_functor& a1, const lambda_functor& a2, - const lambda_functor& a3) { - return - lambda_functor_base< - forloop_no_body_action, - tuple, lambda_functor, - lambda_functor > - > - ( tuple, lambda_functor, - lambda_functor >(a1, a2, a3) ); -} - -// While loop -template -inline const -lambda_functor< - lambda_functor_base< - whileloop_action, - tuple, lambda_functor > - > -> -while_loop(const lambda_functor& a1, const lambda_functor& a2) { - return - lambda_functor_base< - whileloop_action, - tuple, lambda_functor > - > - ( tuple, lambda_functor >(a1, a2)); -} - -// No body case. -template -inline const -lambda_functor< - lambda_functor_base< - whileloop_no_body_action, - tuple > - > -> -while_loop(const lambda_functor& a1) { - return - lambda_functor_base< - whileloop_no_body_action, - tuple > - > - ( tuple >(a1) ); -} - - -// Do While loop -template -inline const -lambda_functor< - lambda_functor_base< - dowhileloop_action, - tuple, lambda_functor > - > -> -do_while_loop(const lambda_functor& a1, const lambda_functor& a2) { - return - lambda_functor_base< - dowhileloop_action, - tuple, lambda_functor > - > - ( tuple, lambda_functor >(a1, a2)); -} - -// No body case. -template -inline const -lambda_functor< - lambda_functor_base< - dowhileloop_no_body_action, - tuple > - > -> -do_while_loop(const lambda_functor& a1) { - return - lambda_functor_base< - dowhileloop_no_body_action, - tuple > - > - ( tuple >(a1)); -} - - -// If Then -template -inline const -lambda_functor< - lambda_functor_base< - ifthen_action, - tuple, lambda_functor > - > -> -if_then(const lambda_functor& a1, const lambda_functor& a2) { - return - lambda_functor_base< - ifthen_action, - tuple, lambda_functor > - > - ( tuple, lambda_functor >(a1, a2) ); -} - -// If then else - -template -inline const -lambda_functor< - lambda_functor_base< - ifthenelse_action, - tuple, lambda_functor, lambda_functor > - > -> -if_then_else(const lambda_functor& a1, const lambda_functor& a2, - const lambda_functor& a3) { - return - lambda_functor_base< - ifthenelse_action, - tuple, lambda_functor, lambda_functor > - > - (tuple, lambda_functor, lambda_functor > - (a1, a2, a3) ); -} - -// Our version of operator?:() - -template -inline const - lambda_functor< - lambda_functor_base< - other_action, - tuple, - typename const_copy_argument::type, - typename const_copy_argument::type> - > -> -if_then_else_return(const lambda_functor& a1, - const Arg2 & a2, - const Arg3 & a3) { - return - lambda_functor_base< - other_action, - tuple, - typename const_copy_argument::type, - typename const_copy_argument::type> - > ( tuple, - typename const_copy_argument::type, - typename const_copy_argument::type> (a1, a2, a3) ); -} - -namespace detail { - -// return type specialization for conditional expression begins ----------- -// start reading below and move upwards - -// PHASE 6:1 -// check if A is conbertible to B and B to A -template -struct return_type_2_ifthenelsereturn; - -// if A can be converted to B and vice versa -> ambiguous -template -struct return_type_2_ifthenelsereturn { - typedef - detail::return_type_deduction_failure type; - // ambiguous type in conditional expression -}; -// if A can be converted to B and vice versa and are of same type -template -struct return_type_2_ifthenelsereturn { - typedef A type; -}; - - -// A can be converted to B -template -struct return_type_2_ifthenelsereturn { - typedef B type; -}; - -// B can be converted to A -template -struct return_type_2_ifthenelsereturn { - typedef A type; -}; - -// neither can be converted. Then we drop the potential references, and -// try again -template -struct return_type_2_ifthenelsereturn<1, false, false, false, A, B> { - // it is safe to add const, since the result will be an rvalue and thus - // const anyway. The const are needed eg. if the types - // are 'const int*' and 'void *'. The remaining type should be 'const void*' - typedef const typename boost::remove_reference::type plainA; - typedef const typename boost::remove_reference::type plainB; - // TODO: Add support for volatile ? - - typedef typename - return_type_2_ifthenelsereturn< - 2, - boost::is_convertible::value, - boost::is_convertible::value, - boost::is_same::value, - plainA, - plainB>::type type; -}; - -// PHASE 6:2 -template -struct return_type_2_ifthenelsereturn<2, false, false, false, A, B> { - typedef - detail::return_type_deduction_failure type; - // types_do_not_match_in_conditional_expression -}; - - - -// PHASE 5: now we know that types are not arithmetic. -template -struct non_numeric_types { - typedef typename - return_type_2_ifthenelsereturn< - 1, // phase 1 - is_convertible::value, - is_convertible::value, - is_same::value, - A, - B>::type type; -}; - -// PHASE 4 : -// the base case covers arithmetic types with differing promote codes -// use the type deduction of arithmetic_actions -template -struct arithmetic_or_not { - typedef typename - return_type_2, A, B>::type type; - // plus_action is just a random pick, has to be a concrete instance -}; - -// this case covers the case of artihmetic types with the same promote codes. -// non numeric deduction is used since e.g. integral promotion is not -// performed with operator ?: -template -struct arithmetic_or_not { - typedef typename non_numeric_types::type type; -}; - -// if either A or B has promote code -1 it is not an arithmetic type -template -struct arithmetic_or_not <-1, -1, A, B> { - typedef typename non_numeric_types::type type; -}; -template -struct arithmetic_or_not <-1, CodeB, A, B> { - typedef typename non_numeric_types::type type; -}; -template -struct arithmetic_or_not { - typedef typename non_numeric_types::type type; -}; - - - - -// PHASE 3 : Are the types same? -// No, check if they are arithmetic or not -template -struct same_or_not { - typedef typename detail::remove_reference_and_cv::type plainA; - typedef typename detail::remove_reference_and_cv::type plainB; - - typedef typename - arithmetic_or_not< - detail::promote_code::value, - detail::promote_code::value, - A, - B>::type type; -}; -// Yes, clear. -template struct same_or_not { - typedef A type; -}; - -} // detail - -// PHASE 2 : Perform first the potential array_to_pointer conversion -template -struct return_type_2, A, B> { - - typedef typename detail::array_to_pointer::type A1; - typedef typename detail::array_to_pointer::type B1; - - typedef typename - boost::add_const::type>::type type; -}; - -// PHASE 1 : Deduction is based on the second and third operand - - -// return type specialization for conditional expression ends ----------- - - - - -// Control loop lambda_functor_base specializations. - -// Specialization for for_loop. -template -class -lambda_functor_base { -public: - Args args; - template struct sig { typedef void type; }; -public: - explicit lambda_functor_base(const Args& a) : args(a) {} - - template - RET call(CALL_FORMAL_ARGS) const { - for(detail::select(boost::tuples::get<0>(args), CALL_ACTUAL_ARGS); - detail::select(boost::tuples::get<1>(args), CALL_ACTUAL_ARGS); - detail::select(boost::tuples::get<2>(args), CALL_ACTUAL_ARGS)) - - detail::select(boost::tuples::get<3>(args), CALL_ACTUAL_ARGS); - } -}; - -// No body case -template -class -lambda_functor_base { -public: - Args args; - template struct sig { typedef void type; }; -public: - explicit lambda_functor_base(const Args& a) : args(a) {} - - template - RET call(CALL_FORMAL_ARGS) const { - for(detail::select(boost::tuples::get<0>(args), CALL_ACTUAL_ARGS); - detail::select(boost::tuples::get<1>(args), CALL_ACTUAL_ARGS); - detail::select(boost::tuples::get<2>(args), CALL_ACTUAL_ARGS)) {} - } -}; - - -// Specialization for while_loop. -template -class -lambda_functor_base { -public: - Args args; - template struct sig { typedef void type; }; -public: - explicit lambda_functor_base(const Args& a) : args(a) {} - - template - RET call(CALL_FORMAL_ARGS) const { - while(detail::select(boost::tuples::get<0>(args), CALL_ACTUAL_ARGS)) - - detail::select(boost::tuples::get<1>(args), CALL_ACTUAL_ARGS); - } -}; - -// No body case -template -class -lambda_functor_base { -public: - Args args; - template struct sig { typedef void type; }; -public: - explicit lambda_functor_base(const Args& a) : args(a) {} - - template - RET call(CALL_FORMAL_ARGS) const { - while(detail::select(boost::tuples::get<0>(args), CALL_ACTUAL_ARGS)) {} - } -}; - -// Specialization for do_while_loop. -// Note that the first argument is the condition. -template -class -lambda_functor_base { -public: - Args args; - template struct sig { typedef void type; }; -public: - explicit lambda_functor_base(const Args& a) : args(a) {} - - template - RET call(CALL_FORMAL_ARGS) const { - do { - detail::select(boost::tuples::get<1>(args), CALL_ACTUAL_ARGS); - } while (detail::select(boost::tuples::get<0>(args), CALL_ACTUAL_ARGS) ); - } -}; - -// No body case -template -class -lambda_functor_base { -public: - Args args; - template struct sig { typedef void type; }; -public: - explicit lambda_functor_base(const Args& a) : args(a) {} - - template - RET call(CALL_FORMAL_ARGS) const { - do {} while (detail::select(boost::tuples::get<0>(args), CALL_ACTUAL_ARGS) ); - } -}; - - -// Specialization for if_then. -template -class -lambda_functor_base { -public: - Args args; - template struct sig { typedef void type; }; -public: - explicit lambda_functor_base(const Args& a) : args(a) {} - - template - RET call(CALL_FORMAL_ARGS) const { - if (detail::select(boost::tuples::get<0>(args), CALL_ACTUAL_ARGS)) detail::select(boost::tuples::get<1>(args), CALL_ACTUAL_ARGS); - } -}; - -// Specialization for if_then_else. -template -class -lambda_functor_base { -public: - Args args; - template struct sig { typedef void type; }; -public: - explicit lambda_functor_base(const Args& a) : args(a) {} - - template - RET call(CALL_FORMAL_ARGS) const { - if (detail::select(boost::tuples::get<0>(args), CALL_ACTUAL_ARGS)) - detail::select(boost::tuples::get<1>(args), CALL_ACTUAL_ARGS); - else - detail::select(boost::tuples::get<2>(args), CALL_ACTUAL_ARGS); - } -}; - -// Specialization of lambda_functor_base for if_then_else_return. -template -class -lambda_functor_base, Args> { -public: - Args args; - - template struct sig { - private: - typedef typename detail::nth_return_type_sig<1, Args, SigArgs>::type ret1; - typedef typename detail::nth_return_type_sig<2, Args, SigArgs>::type ret2; - public: - typedef typename return_type_2< - other_action, ret1, ret2 - >::type type; - }; - -public: - explicit lambda_functor_base(const Args& a) : args(a) {} - - template - RET call(CALL_FORMAL_ARGS) const { - return (detail::select(boost::tuples::get<0>(args), CALL_ACTUAL_ARGS)) ? - detail::select(boost::tuples::get<1>(args), CALL_ACTUAL_ARGS) - : - detail::select(boost::tuples::get<2>(args), CALL_ACTUAL_ARGS); - } -}; - -} // lambda -} // boost - -#endif // BOOST_LAMBDA_CONTROL_CONSTRUCTS_HPP diff --git a/include/boost/lambda/detail/function_adaptors.hpp b/include/boost/lambda/detail/function_adaptors.hpp index c30cbc6..cfe3b07 100644 --- a/include/boost/lambda/detail/function_adaptors.hpp +++ b/include/boost/lambda/detail/function_adaptors.hpp @@ -12,25 +12,167 @@ #ifndef BOOST_LAMBDA_FUNCTION_ADAPTORS_HPP #define BOOST_LAMBDA_FUNCTION_ADAPTORS_HPP +#include "boost/mpl/has_xxx.hpp" +#include "boost/tuple/tuple.hpp" #include "boost/type_traits/same_traits.hpp" +#include "boost/type_traits/remove_reference.hpp" +#include "boost/utility/result_of.hpp" namespace boost { namespace lambda { +namespace detail { + +BOOST_MPL_HAS_XXX_TEMPLATE_NAMED_DEF(has_template_sig, sig, 1, true) + +template +struct remove_references_from_elements { + typedef typename boost::tuples::cons< + typename boost::remove_reference::type, + typename remove_references_from_elements::type + > type; +}; + +template<> +struct remove_references_from_elements { + typedef boost::tuples::null_type type; +}; + +} + template struct function_adaptor { + typedef typename detail::remove_reference_and_cv::type plainF; + +#if !defined(BOOST_NO_RESULT_OF) + // Support functors that use the boost::result_of return type convention. + template + struct result_converter; + template + struct result_converter + : plainF::template sig< + typename detail::remove_references_from_elements::type + > + {}; + template + struct result_converter + : result_of + {}; + template + struct result_converter + : result_of::type) + > + {}; + template + struct result_converter + : result_of::type, + typename tuples::element<2, Tuple>::type) + > + {}; + template + struct result_converter + : result_of::type, + typename tuples::element<2, Tuple>::type, + typename tuples::element<3, Tuple>::type) + > + {}; + template + struct result_converter + : result_of::type, + typename tuples::element<2, Tuple>::type, + typename tuples::element<3, Tuple>::type, + typename tuples::element<4, Tuple>::type) + > + {}; + template + struct result_converter + : result_of::type, + typename tuples::element<2, Tuple>::type, + typename tuples::element<3, Tuple>::type, + typename tuples::element<4, Tuple>::type, + typename tuples::element<5, Tuple>::type) + > + {}; + template + struct result_converter + : result_of::type, + typename tuples::element<2, Tuple>::type, + typename tuples::element<3, Tuple>::type, + typename tuples::element<4, Tuple>::type, + typename tuples::element<5, Tuple>::type, + typename tuples::element<6, Tuple>::type) + > + {}; + template + struct result_converter + : result_of::type, + typename tuples::element<2, Tuple>::type, + typename tuples::element<3, Tuple>::type, + typename tuples::element<4, Tuple>::type, + typename tuples::element<5, Tuple>::type, + typename tuples::element<6, Tuple>::type, + typename tuples::element<7, Tuple>::type) + > + {}; + template + struct result_converter + : result_of::type, + typename tuples::element<2, Tuple>::type, + typename tuples::element<3, Tuple>::type, + typename tuples::element<4, Tuple>::type, + typename tuples::element<5, Tuple>::type, + typename tuples::element<6, Tuple>::type, + typename tuples::element<7, Tuple>::type, + typename tuples::element<8, Tuple>::type) + > + {}; + template + struct result_converter + : result_of::type, + typename tuples::element<2, Tuple>::type, + typename tuples::element<3, Tuple>::type, + typename tuples::element<4, Tuple>::type, + typename tuples::element<5, Tuple>::type, + typename tuples::element<6, Tuple>::type, + typename tuples::element<7, Tuple>::type, + typename tuples::element<8, Tuple>::type, + typename tuples::element<9, Tuple>::type) + > + {}; + // we do not know the return type off-hand, we must ask it from Func - template class sig { - typedef typename Args::head_type F; + // To sig we pass a cons list, where the head is the function object type + // itself (potentially cv-qualified) + // and the tail contains the types of the actual arguments to be passed + // to the function object. The arguments can be cv qualified + // as well. + template + struct sig + : result_converter< + Args + , tuples::length::value + , detail::has_template_sig::value + > + {}; +#else // BOOST_NO_RESULT_OF + + template class sig { typedef typename detail::remove_reference_and_cv::type plainF; public: - // To sig we pass a cons list, where the head is the function object type - // itself (potentially cv-qualified) - // and the tail contains the types of the actual arguments to be passed - // to the function object. The arguments can be cv qualified - // as well. - typedef typename plainF::template sig::type type; + typedef typename plainF::template sig< + typename detail::remove_references_from_elements::type + >::type type; }; +#endif template static RET apply(A1& a1) { diff --git a/include/boost/lambda/detail/lambda_functor_base.hpp b/include/boost/lambda/detail/lambda_functor_base.hpp index e5bb02a..b084acd 100644 --- a/include/boost/lambda/detail/lambda_functor_base.hpp +++ b/include/boost/lambda/detail/lambda_functor_base.hpp @@ -13,6 +13,12 @@ #ifndef BOOST_LAMBDA_LAMBDA_FUNCTOR_BASE_HPP #define BOOST_LAMBDA_LAMBDA_FUNCTOR_BASE_HPP +#include "boost/type_traits/add_reference.hpp" +#include "boost/type_traits/add_const.hpp" +#include "boost/type_traits/remove_const.hpp" +#include "boost/lambda/detail/lambda_fwd.hpp" +#include "boost/lambda/detail/lambda_traits.hpp" + namespace boost { namespace lambda { @@ -40,7 +46,7 @@ public: explicit identity(par_t t) : elem(t) {} template - struct sig { typedef element_t type; }; + struct sig { typedef typename boost::remove_const::type type; }; template RET call(CALL_FORMAL_ARGS) const { CALL_USE_ARGS; return elem; } @@ -377,7 +383,7 @@ public: \ \ template struct sig { \ typedef typename \ - detail::deduce_non_ref_argument_types::type rets_t; \ + detail::deduce_argument_types::type rets_t; \ public: \ typedef typename \ return_type_N_prot::type type; \ diff --git a/include/boost/lambda/detail/lambda_functors.hpp b/include/boost/lambda/detail/lambda_functors.hpp index 5187c7d..9b1b082 100644 --- a/include/boost/lambda/detail/lambda_functors.hpp +++ b/include/boost/lambda/detail/lambda_functors.hpp @@ -161,6 +161,25 @@ public: inherited::template sig::type nullary_return_type; + // Support for boost::result_of. + template struct result; + template + struct result { + typedef nullary_return_type type; + }; + template + struct result { + typedef typename sig >::type type; + }; + template + struct result { + typedef typename sig >::type type; + }; + template + struct result { + typedef typename sig >::type type; + }; + nullary_return_type operator()() const { return inherited::template call diff --git a/include/boost/lambda/detail/lambda_traits.hpp b/include/boost/lambda/detail/lambda_traits.hpp index 0e683c2..f35fa09 100644 --- a/include/boost/lambda/detail/lambda_traits.hpp +++ b/include/boost/lambda/detail/lambda_traits.hpp @@ -16,6 +16,7 @@ #include "boost/type_traits/cv_traits.hpp" #include "boost/type_traits/function_traits.hpp" #include "boost/type_traits/object_traits.hpp" +#include "boost/tuple/tuple.hpp" namespace boost { namespace lambda { diff --git a/include/boost/lambda/detail/operators.hpp b/include/boost/lambda/detail/operators.hpp index 29eb106..149e1ee 100644 --- a/include/boost/lambda/detail/operators.hpp +++ b/include/boost/lambda/detail/operators.hpp @@ -37,16 +37,16 @@ inline const \ lambda_functor< \ lambda_functor_base< \ ACTION, \ - tuple, typename CONVERSION ::type> \ + tuple, typename const_copy_argument ::type> \ > \ > \ OPER_NAME (const lambda_functor& a, CONSTB& b) { \ return \ lambda_functor_base< \ ACTION, \ - tuple, typename CONVERSION ::type> \ + tuple, typename const_copy_argument ::type>\ > \ - (tuple, typename CONVERSION ::type>(a, b)); \ + (tuple, typename const_copy_argument ::type>(a, b)); \ } diff --git a/include/boost/lambda/detail/return_type_traits.hpp b/include/boost/lambda/detail/return_type_traits.hpp index d609e52..bf2394e 100644 --- a/include/boost/lambda/detail/return_type_traits.hpp +++ b/include/boost/lambda/detail/return_type_traits.hpp @@ -216,8 +216,6 @@ typedef typename // currently there are no protectable actions with > 2 args - // Note, that if there will be, lambda_functor_base will have to be - // changed to not get rid of references in Args elements template struct return_type_N_prot { typedef typename return_type_N::type type; diff --git a/include/boost/lambda/exceptions.hpp b/include/boost/lambda/exceptions.hpp index addb275..4f7e895 100644 --- a/include/boost/lambda/exceptions.hpp +++ b/include/boost/lambda/exceptions.hpp @@ -14,6 +14,7 @@ #if !defined(BOOST_LAMBDA_EXCEPTIONS_HPP) #define BOOST_LAMBDA_EXCEPTIONS_HPP +#include "boost/lambda/core.hpp" #include "boost/lambda/detail/control_constructs_common.hpp" namespace boost { diff --git a/test/Jamfile b/test/Jamfile index 4080eb3..7e1a5a7 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -30,5 +30,6 @@ test-suite lambda [ run operator_tests_simple.cpp ] [ run phoenix_control_structures.cpp ] [ run switch_construct.cpp ] + [ run result_of_tests.cpp ] [ run ret_test.cpp ] ; diff --git a/test/bind_tests_advanced.cpp b/test/bind_tests_advanced.cpp index a891f91..d696e49 100644 --- a/test/bind_tests_advanced.cpp +++ b/test/bind_tests_advanced.cpp @@ -2,6 +2,7 @@ // // Copyright (C) 2000-2003 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi) // Copyright (C) 2000-2003 Gary Powell (powellg@amazon.com) +// Copyright (C) 2010 Steven Watanabe // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at @@ -19,6 +20,9 @@ #include "boost/any.hpp" +#include "boost/type_traits/is_reference.hpp" +#include "boost/mpl/assert.hpp" +#include "boost/mpl/if.hpp" #include @@ -352,6 +356,55 @@ void test_break_const() BOOST_CHECK(i == 3); } +template +struct func { + template + struct sig { + typedef typename boost::tuples::element<1, Args>::type arg1; + // If the argument type is not the same as the expected type, + // return void, which will cause an error. Note that we + // can't just assert that the types are the same, because + // both const and non-const versions can be instantiated + // even though only one is ultimately used. + typedef typename boost::mpl::if_, + typename boost::remove_const::type, + void + >::type type; + }; + template + U operator()(const U& arg) const { + return arg; + } +}; + +void test_sig() +{ + int i = 1; + BOOST_CHECK(bind(func(), 1)() == 1); + BOOST_CHECK(bind(func(), _1)(static_cast(i)) == 1); + BOOST_CHECK(bind(func(), _1)(i) == 1); +} + +class base { +public: + virtual int foo() = 0; +}; + +class derived : public base { +public: + virtual int foo() { + return 1; + } +}; + +void test_abstract() +{ + derived d; + base& b = d; + BOOST_CHECK(bind(&base::foo, var(b))() == 1); + BOOST_CHECK(bind(&base::foo, *_1)(&b) == 1); +} + int test_main(int, char *[]) { test_nested_binds(); @@ -361,17 +414,7 @@ int test_main(int, char *[]) { test_const_parameters(); test_rvalue_arguments(); test_break_const(); + test_sig(); + test_abstract(); return 0; } - - - - - - - - - - - - diff --git a/test/cast_test.cpp b/test/cast_test.cpp index 941b42f..eba4300 100644 --- a/test/cast_test.cpp +++ b/test/cast_test.cpp @@ -29,7 +29,7 @@ class base { public: virtual std::string class_name() const { return "const base"; } virtual std::string class_name() { return "base"; } - + virtual ~base() {} }; class derived : public base { diff --git a/test/operator_tests_simple.cpp b/test/operator_tests_simple.cpp index aa3069d..34711fb 100644 --- a/test/operator_tests_simple.cpp +++ b/test/operator_tests_simple.cpp @@ -235,6 +235,22 @@ void compound_operators() { (_1 %= 2)(i); BOOST_CHECK(i == 1); + // lambda expression as a left operand with rvalue on RHS + (_1 += (0 + 1))(i); + BOOST_CHECK(i == 2); + + (_1 -= (0 + 1))(i); + BOOST_CHECK(i == 1); + + (_1 *= (0 + 10))(i); + BOOST_CHECK(i == 10); + + (_1 /= (0 + 2))(i); + BOOST_CHECK(i == 5); + + (_1 %= (0 + 2))(i); + BOOST_CHECK(i == 1); + // shifts unsigned int ui = 2; (_1 <<= 1)(ui); diff --git a/test/result_of_tests.cpp b/test/result_of_tests.cpp new file mode 100644 index 0000000..9047f5b --- /dev/null +++ b/test/result_of_tests.cpp @@ -0,0 +1,314 @@ +// result_of_tests.cpp -- The Boost Lambda Library ------------------ +// +// Copyright (C) 2010 Steven Watanabe +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// For more information, see www.boost.org + +// ----------------------------------------------------------------------- + + +#include // see "Header Implementation Option" +#include +#include +#include +#include + +struct with_result_type { + typedef int result_type; + int operator()() const { return 0; } + int operator()(int) const { return 1; } + int operator()(int, int) const { return 2; } + int operator()(int, int, int) const { return 3; } + int operator()(int, int, int, int) const { return 4; } + int operator()(int, int, int, int, int) const { return 5; } + int operator()(int, int, int, int, int, int) const { return 6; } + int operator()(int, int, int, int, int, int, int) const { return 7; } + int operator()(int, int, int, int, int, int, int, int) const { return 8; } + int operator()(int, int, int, int, int, int, int, int, int) const { return 9; } +}; + +struct with_result_template_value { + template + struct result; + template + struct result { + typedef int type; + }; + template + struct result { + BOOST_MPL_ASSERT((boost::is_same)); + typedef int type; + }; + template + struct result { + BOOST_MPL_ASSERT((boost::is_same)); + BOOST_MPL_ASSERT((boost::is_same)); + typedef int type; + }; + template + struct result { + BOOST_MPL_ASSERT((boost::is_same)); + BOOST_MPL_ASSERT((boost::is_same)); + BOOST_MPL_ASSERT((boost::is_same)); + typedef int type; + }; + template + struct result { + BOOST_MPL_ASSERT((boost::is_same)); + BOOST_MPL_ASSERT((boost::is_same)); + BOOST_MPL_ASSERT((boost::is_same)); + BOOST_MPL_ASSERT((boost::is_same)); + typedef int type; + }; + template + struct result { + BOOST_MPL_ASSERT((boost::is_same)); + BOOST_MPL_ASSERT((boost::is_same)); + BOOST_MPL_ASSERT((boost::is_same)); + BOOST_MPL_ASSERT((boost::is_same)); + BOOST_MPL_ASSERT((boost::is_same)); + typedef int type; + }; + template + struct result { + BOOST_MPL_ASSERT((boost::is_same)); + BOOST_MPL_ASSERT((boost::is_same)); + BOOST_MPL_ASSERT((boost::is_same)); + BOOST_MPL_ASSERT((boost::is_same)); + BOOST_MPL_ASSERT((boost::is_same)); + BOOST_MPL_ASSERT((boost::is_same)); + typedef int type; + }; + template + struct result { + BOOST_MPL_ASSERT((boost::is_same)); + BOOST_MPL_ASSERT((boost::is_same)); + BOOST_MPL_ASSERT((boost::is_same)); + BOOST_MPL_ASSERT((boost::is_same)); + BOOST_MPL_ASSERT((boost::is_same)); + BOOST_MPL_ASSERT((boost::is_same)); + BOOST_MPL_ASSERT((boost::is_same)); + typedef int type; + }; + template + struct result { + BOOST_MPL_ASSERT((boost::is_same)); + BOOST_MPL_ASSERT((boost::is_same)); + BOOST_MPL_ASSERT((boost::is_same)); + BOOST_MPL_ASSERT((boost::is_same)); + BOOST_MPL_ASSERT((boost::is_same)); + BOOST_MPL_ASSERT((boost::is_same)); + BOOST_MPL_ASSERT((boost::is_same)); + BOOST_MPL_ASSERT((boost::is_same)); + typedef int type; + }; + template + struct result { + BOOST_MPL_ASSERT((boost::is_same)); + BOOST_MPL_ASSERT((boost::is_same)); + BOOST_MPL_ASSERT((boost::is_same)); + BOOST_MPL_ASSERT((boost::is_same)); + BOOST_MPL_ASSERT((boost::is_same)); + BOOST_MPL_ASSERT((boost::is_same)); + BOOST_MPL_ASSERT((boost::is_same)); + BOOST_MPL_ASSERT((boost::is_same)); + BOOST_MPL_ASSERT((boost::is_same)); + typedef int type; + }; + + int operator()() const { return 0; } + int operator()(int) const { return 1; } + int operator()(int, int) const { return 2; } + int operator()(int, int, int) const { return 3; } + int operator()(int, int, int, int) const { return 4; } + int operator()(int, int, int, int, int) const { return 5; } + int operator()(int, int, int, int, int, int) const { return 6; } + int operator()(int, int, int, int, int, int, int) const { return 7; } + int operator()(int, int, int, int, int, int, int, int) const { return 8; } + int operator()(int, int, int, int, int, int, int, int, int) const { return 9; } +}; + +struct with_result_template_reference { + template + struct result; + template + struct result { + typedef int type; + }; + template + struct result { + BOOST_MPL_ASSERT((boost::is_same)); + typedef int type; + }; + template + struct result { + BOOST_MPL_ASSERT((boost::is_same)); + BOOST_MPL_ASSERT((boost::is_same)); + typedef int type; + }; + template + struct result { + BOOST_MPL_ASSERT((boost::is_same)); + BOOST_MPL_ASSERT((boost::is_same)); + BOOST_MPL_ASSERT((boost::is_same)); + typedef int type; + }; + template + struct result { + BOOST_MPL_ASSERT((boost::is_same)); + BOOST_MPL_ASSERT((boost::is_same)); + BOOST_MPL_ASSERT((boost::is_same)); + BOOST_MPL_ASSERT((boost::is_same)); + typedef int type; + }; + template + struct result { + BOOST_MPL_ASSERT((boost::is_same)); + BOOST_MPL_ASSERT((boost::is_same)); + BOOST_MPL_ASSERT((boost::is_same)); + BOOST_MPL_ASSERT((boost::is_same)); + BOOST_MPL_ASSERT((boost::is_same)); + typedef int type; + }; + template + struct result { + BOOST_MPL_ASSERT((boost::is_same)); + BOOST_MPL_ASSERT((boost::is_same)); + BOOST_MPL_ASSERT((boost::is_same)); + BOOST_MPL_ASSERT((boost::is_same)); + BOOST_MPL_ASSERT((boost::is_same)); + BOOST_MPL_ASSERT((boost::is_same)); + typedef int type; + }; + template + struct result { + BOOST_MPL_ASSERT((boost::is_same)); + BOOST_MPL_ASSERT((boost::is_same)); + BOOST_MPL_ASSERT((boost::is_same)); + BOOST_MPL_ASSERT((boost::is_same)); + BOOST_MPL_ASSERT((boost::is_same)); + BOOST_MPL_ASSERT((boost::is_same)); + BOOST_MPL_ASSERT((boost::is_same)); + typedef int type; + }; + template + struct result { + BOOST_MPL_ASSERT((boost::is_same)); + BOOST_MPL_ASSERT((boost::is_same)); + BOOST_MPL_ASSERT((boost::is_same)); + BOOST_MPL_ASSERT((boost::is_same)); + BOOST_MPL_ASSERT((boost::is_same)); + BOOST_MPL_ASSERT((boost::is_same)); + BOOST_MPL_ASSERT((boost::is_same)); + BOOST_MPL_ASSERT((boost::is_same)); + typedef int type; + }; + template + struct result { + BOOST_MPL_ASSERT((boost::is_same)); + BOOST_MPL_ASSERT((boost::is_same)); + BOOST_MPL_ASSERT((boost::is_same)); + BOOST_MPL_ASSERT((boost::is_same)); + BOOST_MPL_ASSERT((boost::is_same)); + BOOST_MPL_ASSERT((boost::is_same)); + BOOST_MPL_ASSERT((boost::is_same)); + BOOST_MPL_ASSERT((boost::is_same)); + BOOST_MPL_ASSERT((boost::is_same)); + typedef int type; + }; + + int operator()() const { return 0; } + int operator()(int) const { return 1; } + int operator()(int, int) const { return 2; } + int operator()(int, int, int) const { return 3; } + int operator()(int, int, int, int) const { return 4; } + int operator()(int, int, int, int, int) const { return 5; } + int operator()(int, int, int, int, int, int) const { return 6; } + int operator()(int, int, int, int, int, int, int) const { return 7; } + int operator()(int, int, int, int, int, int, int, int) const { return 8; } + int operator()(int, int, int, int, int, int, int, int, int) const { return 9; } +}; + +template +typename boost::result_of::type apply0(F f) { + return f(); +} +template +typename boost::result_of::type apply1(F f, A a) { + return f(a); +} +template +typename boost::result_of::type apply2(F f, A a, B b) { + return f(a, b); +} +template +typename boost::result_of::type apply3(F f, A a, B b, C c) { + return f(a, b, c); +} + +using namespace boost::lambda; + +int test_main(int, char *[]) { + BOOST_CHECK(boost::lambda::bind(with_result_type())() == 0); + BOOST_CHECK(boost::lambda::bind(with_result_type(), 1)() == 1); + BOOST_CHECK(boost::lambda::bind(with_result_type(), 1, 2)() == 2); + BOOST_CHECK(boost::lambda::bind(with_result_type(), 1, 2, 3)() == 3); + BOOST_CHECK(boost::lambda::bind(with_result_type(), 1, 2, 3, 4)() == 4); + BOOST_CHECK(boost::lambda::bind(with_result_type(), 1, 2, 3, 4, 5)() == 5); + BOOST_CHECK(boost::lambda::bind(with_result_type(), 1, 2, 3, 4, 5, 6)() == 6); + BOOST_CHECK(boost::lambda::bind(with_result_type(), 1, 2, 3, 4, 5, 6, 7)() == 7); + BOOST_CHECK(boost::lambda::bind(with_result_type(), 1, 2, 3, 4, 5, 6, 7, 8)() == 8); + BOOST_CHECK(boost::lambda::bind(with_result_type(), 1, 2, 3, 4, 5, 6, 7, 8, 9)() == 9); + + // Nullary result_of fails + //BOOST_CHECK(boost::lambda::bind(with_result_template_value())() == 0); + BOOST_CHECK(boost::lambda::bind(with_result_template_value(), 1)() == 1); + BOOST_CHECK(boost::lambda::bind(with_result_template_value(), 1, 2)() == 2); + BOOST_CHECK(boost::lambda::bind(with_result_template_value(), 1, 2, 3)() == 3); + BOOST_CHECK(boost::lambda::bind(with_result_template_value(), 1, 2, 3, 4)() == 4); + BOOST_CHECK(boost::lambda::bind(with_result_template_value(), 1, 2, 3, 4, 5)() == 5); + BOOST_CHECK(boost::lambda::bind(with_result_template_value(), 1, 2, 3, 4, 5, 6)() == 6); + BOOST_CHECK(boost::lambda::bind(with_result_template_value(), 1, 2, 3, 4, 5, 6, 7)() == 7); + BOOST_CHECK(boost::lambda::bind(with_result_template_value(), 1, 2, 3, 4, 5, 6, 7, 8)() == 8); + BOOST_CHECK(boost::lambda::bind(with_result_template_value(), 1, 2, 3, 4, 5, 6, 7, 8, 9)() == 9); + + int one = 1, + two = 2, + three = 3, + four = 4, + five = 5, + six = 6, + seven = 7, + eight = 8, + nine = 9; + + // Nullary result_of fails + //BOOST_CHECK(boost::lambda::bind(with_result_template_reference())() == 0); + BOOST_CHECK(boost::lambda::bind(with_result_template_reference(), var(one))() == 1); + BOOST_CHECK(boost::lambda::bind(with_result_template_reference(), var(one), var(two))() == 2); + BOOST_CHECK(boost::lambda::bind(with_result_template_reference(), var(one), var(two), var(three))() == 3); + BOOST_CHECK(boost::lambda::bind(with_result_template_reference(), var(one), var(two), var(three), var(four))() == 4); + BOOST_CHECK(boost::lambda::bind(with_result_template_reference(), var(one), var(two), var(three), var(four), var(five))() == 5); + BOOST_CHECK(boost::lambda::bind(with_result_template_reference(), var(one), var(two), var(three), var(four), var(five), var(six))() == 6); + BOOST_CHECK(boost::lambda::bind(with_result_template_reference(), var(one), var(two), var(three), var(four), var(five), var(six), var(seven))() == 7); + BOOST_CHECK(boost::lambda::bind(with_result_template_reference(), var(one), var(two), var(three), var(four), var(five), var(six), var(seven), var(eight))() == 8); + BOOST_CHECK(boost::lambda::bind(with_result_template_reference(), var(one), var(two), var(three), var(four), var(five), var(six), var(seven), var(eight), var(nine))() == 9); + + // Check using result_of with lambda functors + //BOOST_CHECK(apply0(constant(0)) == 0); + BOOST_CHECK(apply1(_1, one) == 1); + BOOST_CHECK(apply1(_1, one) == 1); + BOOST_CHECK(apply1(_1, one) == 1); + BOOST_CHECK((apply2(_1 + _2, one, two) == 3)); + BOOST_CHECK((apply2(_1 + _2, one, two) == 3)); + BOOST_CHECK((apply2(_1 + _2, one, two) == 3)); + BOOST_CHECK((apply3(_1 + _2 + _3, one, two, three) == 6)); + BOOST_CHECK((apply3(_1 + _2 + _3, one, two, three) == 6)); + BOOST_CHECK((apply3(_1 + _2 + _3, one, two, three) == 6)); + + return 0; +}