Chris@16: // Boost Lambda Library - operators.hpp -------------------------------------- Chris@16: Chris@16: // Copyright (C) 1999, 2000 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi) Chris@16: // Chris@16: // Distributed under the Boost Software License, Version 1.0. (See Chris@16: // accompanying file LICENSE_1_0.txt or copy at Chris@16: // http://www.boost.org/LICENSE_1_0.txt) Chris@16: // Chris@16: // For more information, see www.boost.org Chris@16: Chris@16: // --------------------------------------------------------------- Chris@16: Chris@16: #ifndef BOOST_LAMBDA_OPERATORS_HPP Chris@16: #define BOOST_LAMBDA_OPERATORS_HPP Chris@16: Chris@16: #include "boost/lambda/detail/is_instance_of.hpp" Chris@16: Chris@16: namespace boost { Chris@16: namespace lambda { Chris@16: Chris@16: #if defined BOOST_LAMBDA_BE1 Chris@16: #error "Multiple defines of BOOST_LAMBDA_BE1" Chris@16: #endif Chris@16: Chris@16: // For all BOOSTA_LAMBDA_BE* macros: Chris@16: Chris@16: // CONSTA must be either 'A' or 'const A' Chris@16: // CONSTB must be either 'B' or 'const B' Chris@16: Chris@16: // It is stupid to have the names A and B as macro arguments, but it avoids Chris@16: // the need to pass in emtpy macro arguments, which gives warnings on some Chris@16: // compilers Chris@16: Chris@16: #define BOOST_LAMBDA_BE1(OPER_NAME, ACTION, CONSTA, CONSTB, CONVERSION) \ Chris@16: template \ Chris@16: inline const \ Chris@16: lambda_functor< \ Chris@16: lambda_functor_base< \ Chris@16: ACTION, \ Chris@16: tuple, typename const_copy_argument ::type> \ Chris@16: > \ Chris@16: > \ Chris@16: OPER_NAME (const lambda_functor& a, CONSTB& b) { \ Chris@16: return \ Chris@16: lambda_functor_base< \ Chris@16: ACTION, \ Chris@16: tuple, typename const_copy_argument ::type>\ Chris@16: > \ Chris@16: (tuple, typename const_copy_argument ::type>(a, b)); \ Chris@16: } Chris@16: Chris@16: Chris@16: #if defined BOOST_LAMBDA_BE2 Chris@16: #error "Multiple defines of BOOST_LAMBDA_BE2" Chris@16: #endif Chris@16: Chris@16: #define BOOST_LAMBDA_BE2(OPER_NAME, ACTION, CONSTA, CONSTB, CONVERSION) \ Chris@16: template \ Chris@16: inline const \ Chris@16: lambda_functor< \ Chris@16: lambda_functor_base< \ Chris@16: ACTION, \ Chris@16: tuple::type, lambda_functor > \ Chris@16: > \ Chris@16: > \ Chris@16: OPER_NAME (CONSTA& a, const lambda_functor& b) { \ Chris@16: return \ Chris@16: lambda_functor_base< \ Chris@16: ACTION, \ Chris@16: tuple::type, lambda_functor > \ Chris@16: > \ Chris@16: (tuple::type, lambda_functor >(a, b)); \ Chris@16: } Chris@16: Chris@16: Chris@16: #if defined BOOST_LAMBDA_BE3 Chris@16: #error "Multiple defines of BOOST_LAMBDA_BE3" Chris@16: #endif Chris@16: Chris@16: #define BOOST_LAMBDA_BE3(OPER_NAME, ACTION, CONSTA, CONSTB, CONVERSION) \ Chris@16: template \ Chris@16: inline const \ Chris@16: lambda_functor< \ Chris@16: lambda_functor_base< \ Chris@16: ACTION, \ Chris@16: tuple, lambda_functor > \ Chris@16: > \ Chris@16: > \ Chris@16: OPER_NAME (const lambda_functor& a, const lambda_functor& b) { \ Chris@16: return \ Chris@16: lambda_functor_base< \ Chris@16: ACTION, \ Chris@16: tuple, lambda_functor > \ Chris@16: > \ Chris@16: (tuple, lambda_functor >(a, b)); \ Chris@16: } Chris@16: Chris@16: #if defined BOOST_LAMBDA_BE Chris@16: #error "Multiple defines of BOOST_LAMBDA_BE" Chris@16: #endif Chris@16: Chris@16: #define BOOST_LAMBDA_BE(OPER_NAME, ACTION, CONSTA, CONSTB, CONST_CONVERSION) \ Chris@16: BOOST_LAMBDA_BE1(OPER_NAME, ACTION, CONSTA, CONSTB, CONST_CONVERSION) \ Chris@16: BOOST_LAMBDA_BE2(OPER_NAME, ACTION, CONSTA, CONSTB, CONST_CONVERSION) \ Chris@16: BOOST_LAMBDA_BE3(OPER_NAME, ACTION, CONSTA, CONSTB, CONST_CONVERSION) Chris@16: Chris@16: #define BOOST_LAMBDA_EMPTY() Chris@16: Chris@16: BOOST_LAMBDA_BE(operator+, arithmetic_action, const A, const B, const_copy_argument) Chris@16: BOOST_LAMBDA_BE(operator-, arithmetic_action, const A, const B, const_copy_argument) Chris@16: BOOST_LAMBDA_BE(operator*, arithmetic_action, const A, const B, const_copy_argument) Chris@16: BOOST_LAMBDA_BE(operator/, arithmetic_action, const A, const B, const_copy_argument) Chris@16: BOOST_LAMBDA_BE(operator%, arithmetic_action, const A, const B, const_copy_argument) Chris@16: BOOST_LAMBDA_BE(operator<<, bitwise_action, const A, const B, const_copy_argument) Chris@16: BOOST_LAMBDA_BE(operator>>, bitwise_action, const A, const B, const_copy_argument) Chris@16: BOOST_LAMBDA_BE(operator&, bitwise_action, const A, const B, const_copy_argument) Chris@16: BOOST_LAMBDA_BE(operator|, bitwise_action, const A, const B, const_copy_argument) Chris@16: BOOST_LAMBDA_BE(operator^, bitwise_action, const A, const B, const_copy_argument) Chris@16: BOOST_LAMBDA_BE(operator&&, logical_action, const A, const B, const_copy_argument) Chris@16: BOOST_LAMBDA_BE(operator||, logical_action, const A, const B, const_copy_argument) Chris@16: BOOST_LAMBDA_BE(operator<, relational_action, const A, const B, const_copy_argument) Chris@16: BOOST_LAMBDA_BE(operator>, relational_action, const A, const B, const_copy_argument) Chris@16: BOOST_LAMBDA_BE(operator<=, relational_action, const A, const B, const_copy_argument) Chris@16: BOOST_LAMBDA_BE(operator>=, relational_action, const A, const B, const_copy_argument) Chris@16: BOOST_LAMBDA_BE(operator==, relational_action, const A, const B, const_copy_argument) Chris@16: BOOST_LAMBDA_BE(operator!=, relational_action, const A, const B, const_copy_argument) Chris@16: Chris@16: BOOST_LAMBDA_BE(operator+=, arithmetic_assignment_action, A, const B, reference_argument) Chris@16: BOOST_LAMBDA_BE(operator-=, arithmetic_assignment_action, A, const B, reference_argument) Chris@16: BOOST_LAMBDA_BE(operator*=, arithmetic_assignment_action, A, const B, reference_argument) Chris@16: BOOST_LAMBDA_BE(operator/=, arithmetic_assignment_action, A, const B, reference_argument) Chris@16: BOOST_LAMBDA_BE(operator%=, arithmetic_assignment_action, A, const B, reference_argument) Chris@16: BOOST_LAMBDA_BE(operator<<=, bitwise_assignment_action, A, const B, reference_argument) Chris@16: BOOST_LAMBDA_BE(operator>>=, bitwise_assignment_action, A, const B, reference_argument) Chris@16: BOOST_LAMBDA_BE(operator&=, bitwise_assignment_action, A, const B, reference_argument) Chris@16: BOOST_LAMBDA_BE(operator|=, bitwise_assignment_action, A, const B, reference_argument) Chris@16: BOOST_LAMBDA_BE(operator^=, bitwise_assignment_action, A, const B, reference_argument) Chris@16: Chris@16: Chris@16: // A special trick for comma operator for correct preprocessing Chris@16: #if defined BOOST_LAMBDA_COMMA_OPERATOR_NAME Chris@16: #error "Multiple defines of BOOST_LAMBDA_COMMA_OPERATOR_NAME" Chris@16: #endif Chris@16: Chris@16: #define BOOST_LAMBDA_COMMA_OPERATOR_NAME operator, Chris@16: Chris@16: BOOST_LAMBDA_BE1(BOOST_LAMBDA_COMMA_OPERATOR_NAME, other_action, const A, const B, const_copy_argument) Chris@16: BOOST_LAMBDA_BE2(BOOST_LAMBDA_COMMA_OPERATOR_NAME, other_action, const A, const B, const_copy_argument) Chris@16: BOOST_LAMBDA_BE3(BOOST_LAMBDA_COMMA_OPERATOR_NAME, other_action, const A, const B, const_copy_argument) Chris@16: Chris@16: Chris@16: Chris@16: namespace detail { Chris@16: Chris@16: // special cases for ostream& << Any and istream& >> Any --------------- Chris@16: // the actual stream classes may vary and thus a specialisation for, Chris@16: // say ostream& does not match (the general case above is chosen). Chris@16: // Therefore we specialise for non-const reference: Chris@16: // if the left argument is a stream, we store the stream as reference Chris@16: // if it is something else, we store a const plain by default Chris@16: Chris@16: // Note that the overloading is const vs. non-const first argument Chris@16: Chris@16: #ifdef BOOST_NO_TEMPLATED_STREAMS Chris@16: template struct convert_ostream_to_ref_others_to_c_plain_by_default { Chris@16: typedef typename detail::IF< Chris@16: boost::is_convertible::value, Chris@16: T&, Chris@16: typename const_copy_argument ::type Chris@16: >::RET type; Chris@16: }; Chris@16: Chris@16: template struct convert_istream_to_ref_others_to_c_plain_by_default { Chris@16: typedef typename detail::IF< Chris@16: boost::is_convertible::value, Chris@16: T&, Chris@16: typename const_copy_argument ::type Chris@16: >::RET type; Chris@16: }; Chris@16: #else Chris@16: Chris@16: template struct convert_ostream_to_ref_others_to_c_plain_by_default { Chris@16: typedef typename detail::IF< Chris@16: is_instance_of_2< Chris@16: T, std::basic_ostream Chris@16: >::value, Chris@16: T&, Chris@16: typename const_copy_argument ::type Chris@16: >::RET type; Chris@16: }; Chris@16: Chris@16: template struct convert_istream_to_ref_others_to_c_plain_by_default { Chris@16: typedef typename detail::IF< Chris@16: is_instance_of_2< Chris@16: T, std::basic_istream Chris@16: >::value, Chris@16: T&, Chris@16: typename const_copy_argument ::type Chris@16: >::RET type; Chris@16: }; Chris@16: #endif Chris@16: Chris@16: } // detail Chris@16: Chris@16: BOOST_LAMBDA_BE2(operator<<, bitwise_action< leftshift_action>, A, const B, detail::convert_ostream_to_ref_others_to_c_plain_by_default) Chris@16: BOOST_LAMBDA_BE2(operator>>, bitwise_action< rightshift_action>, A, const B, detail::convert_istream_to_ref_others_to_c_plain_by_default) Chris@16: Chris@16: Chris@16: // special case for io_manipulators. Chris@16: // function references cannot be given as arguments to lambda operator Chris@16: // expressions in general. With << and >> the use of manipulators is Chris@16: // so common, that specializations are provided to make them work. Chris@16: Chris@16: template Chris@16: inline const Chris@16: lambda_functor< Chris@16: lambda_functor_base< Chris@16: bitwise_action, Chris@16: tuple, Ret(&)(ManipArg)> Chris@16: > Chris@16: > Chris@16: operator<<(const lambda_functor& a, Ret(&b)(ManipArg)) Chris@16: { Chris@16: return Chris@16: lambda_functor_base< Chris@16: bitwise_action, Chris@16: tuple, Ret(&)(ManipArg)> Chris@16: > Chris@16: ( tuple, Ret(&)(ManipArg)>(a, b) ); Chris@16: } Chris@16: Chris@16: template Chris@16: inline const Chris@16: lambda_functor< Chris@16: lambda_functor_base< Chris@16: bitwise_action, Chris@16: tuple, Ret(&)(ManipArg)> Chris@16: > Chris@16: > Chris@16: operator>>(const lambda_functor& a, Ret(&b)(ManipArg)) Chris@16: { Chris@16: return Chris@16: lambda_functor_base< Chris@16: bitwise_action, Chris@16: tuple, Ret(&)(ManipArg)> Chris@16: > Chris@16: ( tuple, Ret(&)(ManipArg)>(a, b) ); Chris@16: } Chris@16: Chris@16: Chris@16: // (+ and -) take their arguments as const references. Chris@16: // This has consquences with pointer artihmetic Chris@16: // E.g int a[]; ... *a = 1 works but not *(a+1) = 1. Chris@16: // the result of a+1 would be const Chris@16: // To make the latter work too, Chris@16: // non-const arrays are taken as non-const and stored as non-const as well. Chris@16: #if defined BOOST_LAMBDA_PTR_ARITHMETIC_E1 Chris@16: #error "Multiple defines of BOOST_LAMBDA_PTR_ARITHMETIC_E1" Chris@16: #endif Chris@16: Chris@16: #define BOOST_LAMBDA_PTR_ARITHMETIC_E1(OPER_NAME, ACTION, CONSTB) \ Chris@16: template \ Chris@16: inline const \ Chris@16: lambda_functor< \ Chris@16: lambda_functor_base, CONSTB(&)[N]> > \ Chris@16: > \ Chris@16: OPER_NAME (const lambda_functor& a, CONSTB(&b)[N]) \ Chris@16: { \ Chris@16: return \ Chris@16: lambda_functor_base, CONSTB(&)[N]> > \ Chris@16: (tuple, CONSTB(&)[N]>(a, b)); \ Chris@16: } Chris@16: Chris@16: Chris@16: #if defined BOOST_LAMBDA_PTR_ARITHMETIC_E2 Chris@16: #error "Multiple defines of BOOST_LAMBDA_PTR_ARITHMETIC_E2" Chris@16: #endif Chris@16: Chris@16: #define BOOST_LAMBDA_PTR_ARITHMETIC_E2(OPER_NAME, ACTION, CONSTA) \ Chris@16: template \ Chris@16: inline const \ Chris@16: lambda_functor< \ Chris@16: lambda_functor_base > > \ Chris@16: > \ Chris@16: OPER_NAME (CONSTA(&a)[N], const lambda_functor& b) \ Chris@16: { \ Chris@16: return \ Chris@16: lambda_functor_base > > \ Chris@16: (tuple >(a, b)); \ Chris@16: } Chris@16: Chris@16: Chris@16: BOOST_LAMBDA_PTR_ARITHMETIC_E1(operator+, arithmetic_action, B) Chris@16: BOOST_LAMBDA_PTR_ARITHMETIC_E2(operator+, arithmetic_action, A) Chris@16: BOOST_LAMBDA_PTR_ARITHMETIC_E1(operator+, arithmetic_action,const B) Chris@16: BOOST_LAMBDA_PTR_ARITHMETIC_E2(operator+, arithmetic_action,const A) Chris@16: Chris@16: Chris@16: //BOOST_LAMBDA_PTR_ARITHMETIC_E1(operator-, arithmetic_action) Chris@16: // This is not needed, since the result of ptr-ptr is an rvalue anyway Chris@16: Chris@16: BOOST_LAMBDA_PTR_ARITHMETIC_E2(operator-, arithmetic_action, A) Chris@16: BOOST_LAMBDA_PTR_ARITHMETIC_E2(operator-, arithmetic_action, const A) Chris@16: Chris@16: Chris@16: #undef BOOST_LAMBDA_BE1 Chris@16: #undef BOOST_LAMBDA_BE2 Chris@16: #undef BOOST_LAMBDA_BE3 Chris@16: #undef BOOST_LAMBDA_BE Chris@16: #undef BOOST_LAMBDA_COMMA_OPERATOR_NAME Chris@16: Chris@16: #undef BOOST_LAMBDA_PTR_ARITHMETIC_E1 Chris@16: #undef BOOST_LAMBDA_PTR_ARITHMETIC_E2 Chris@16: Chris@16: Chris@16: // --------------------------------------------------------------------- Chris@16: // unary operators ----------------------------------------------------- Chris@16: // --------------------------------------------------------------------- Chris@16: Chris@16: #if defined BOOST_LAMBDA_UE Chris@16: #error "Multiple defines of BOOST_LAMBDA_UE" Chris@16: #endif Chris@16: Chris@16: #define BOOST_LAMBDA_UE(OPER_NAME, ACTION) \ Chris@16: template \ Chris@16: inline const \ Chris@16: lambda_functor > > > \ Chris@16: OPER_NAME (const lambda_functor& a) \ Chris@16: { \ Chris@16: return \ Chris@16: lambda_functor_base > > \ Chris@16: ( tuple >(a) ); \ Chris@16: } Chris@16: Chris@16: Chris@16: BOOST_LAMBDA_UE(operator+, unary_arithmetic_action) Chris@16: BOOST_LAMBDA_UE(operator-, unary_arithmetic_action) Chris@16: BOOST_LAMBDA_UE(operator~, bitwise_action) Chris@16: BOOST_LAMBDA_UE(operator!, logical_action) Chris@16: BOOST_LAMBDA_UE(operator++, pre_increment_decrement_action) Chris@16: BOOST_LAMBDA_UE(operator--, pre_increment_decrement_action) Chris@16: BOOST_LAMBDA_UE(operator*, other_action) Chris@16: BOOST_LAMBDA_UE(operator&, other_action) Chris@16: Chris@16: #if defined BOOST_LAMBDA_POSTFIX_UE Chris@16: #error "Multiple defines of BOOST_LAMBDA_POSTFIX_UE" Chris@16: #endif Chris@16: Chris@16: #define BOOST_LAMBDA_POSTFIX_UE(OPER_NAME, ACTION) \ Chris@16: template \ Chris@16: inline const \ Chris@16: lambda_functor > > > \ Chris@16: OPER_NAME (const lambda_functor& a, int) \ Chris@16: { \ Chris@16: return \ Chris@16: lambda_functor_base > > \ Chris@16: ( tuple >(a) ); \ Chris@16: } Chris@16: Chris@16: Chris@16: BOOST_LAMBDA_POSTFIX_UE(operator++, post_increment_decrement_action) Chris@16: BOOST_LAMBDA_POSTFIX_UE(operator--, post_increment_decrement_action) Chris@16: Chris@16: #undef BOOST_LAMBDA_UE Chris@16: #undef BOOST_LAMBDA_POSTFIX_UE Chris@16: Chris@16: } // namespace lambda Chris@16: } // namespace boost Chris@16: Chris@16: #endif