Boost logo

Boost :

From: Steven Watanabe (steven_at_[hidden])
Date: 2006-12-18 14:52:00


AMDG

    Attached is a patch for operators.hpp that resolves
http://sourceforge.net/tracker/index.php?func=detail&aid=1602075&group_id=7586&atid=107586
<http://sourceforge.net/tracker/index.php?func=detail&aid=1602075&group_id=7586&atid=107586>
and a patch for operator_return_type_traits.hpp that
adds specializations for subscript_action with boost::array and
plus_action with std::basic_string. It also fixes the problem
of stripping off const too soon which causes errors with

    #include <ostream>
    #include <string>
    #include <boost/lambda/lambda.hpp>

    int main() {
        const std::string s = "hello";
        std::cout << (boost::lambda::_1[4])(s) << std::endl;
    }

In Christ,
Steven Watanabe


*** operators.hpp.orig Mon Dec 18 10:42:56 2006
--- operators.hpp Mon Dec 18 10:41:56 2006
***************
*** 266,274 ****
> \
  OPER_NAME (const lambda_functor<Arg>& a, CONSTB(&b)[N]) \
  { \
! return lambda_functor< \
      lambda_functor_base<ACTION, tuple<lambda_functor<Arg>, CONSTB(&)[N]> > \
! >(tuple<lambda_functor<Arg>, CONSTB(&)[N]>(a, b)); \
  }
  
  
--- 266,274 ----
> \
  OPER_NAME (const lambda_functor<Arg>& a, CONSTB(&b)[N]) \
  { \
! return \
      lambda_functor_base<ACTION, tuple<lambda_functor<Arg>, CONSTB(&)[N]> > \
! (tuple<lambda_functor<Arg>, CONSTB(&)[N]>(a, b)); \
  }
  
  


*** operator_return_type_traits.hpp.orig Mon Dec 18 10:42:30 2006
--- operator_return_type_traits.hpp Mon Dec 18 11:15:00 2006
***************
*** 1,942 ****
! // operator_return_type_traits.hpp -- Boost Lambda Library ------------------
!
! // Copyright (C) 1999, 2000 Jaakko Järvi (jaakko.jarvi_at_[hidden])
! //
! // 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
!
! #ifndef BOOST_LAMBDA_OPERATOR_RETURN_TYPE_TRAITS_HPP
! #define BOOST_LAMBDA_OPERATOR_RETURN_TYPE_TRAITS_HPP
!
! #include "boost/lambda/detail/is_instance_of.hpp"
! #include "boost/type_traits/same_traits.hpp"
!
! #include "boost/indirect_reference.hpp"
!
! #include <cstddef> // needed for the ptrdiff_t
! #include <iosfwd> // for istream and ostream
!
! #include <iterator> // needed for operator&
!
! namespace boost {
! namespace lambda {
! namespace detail {
!
! // -- general helper templates for type deduction ------------------
!
! // Much of the type deduction code for standard arithmetic types from Gary Powell
!
! template <class A> struct promote_code { static const int value = -1; };
! // this means that a code is not defined for A
!
! // -- the next 5 types are needed in if_then_else_return
! // the promotion order is not important, but they must have distinct values.
! template <> struct promote_code<bool> { static const int value = 10; };
! template <> struct promote_code<char> { static const int value = 20; };
! template <> struct promote_code<unsigned char> { static const int value = 30; };
! template <> struct promote_code<signed char> { static const int value = 40; };
! template <> struct promote_code<short int> { static const int value = 50; };
! // ----------
!
! template <> struct promote_code<int> { static const int value = 100; };
! template <> struct promote_code<unsigned int> { static const int value = 200; };
! template <> struct promote_code<long> { static const int value = 300; };
! template <> struct promote_code<unsigned long> { static const int value = 400; };
!
! template <> struct promote_code<float> { static const int value = 500; };
! template <> struct promote_code<double> { static const int value = 600; };
! template <> struct promote_code<long double> { static const int value = 700; };
!
! // TODO: wchar_t
!
! // forward delcaration of complex.
!
! } // namespace detail
! } // namespace lambda
! } // namespace boost
!
! namespace std {
! template<class T> class complex;
! }
!
! namespace boost {
! namespace lambda {
! namespace detail {
!
! template <> struct promote_code< std::complex<float> > { static const int value = 800; };
! template <> struct promote_code< std::complex<double> > { static const int value = 900; };
! template <> struct promote_code< std::complex<long double> > { static const int value = 1000; };
!
! // -- int promotion -------------------------------------------
! template <class T> struct promote_to_int { typedef T type; };
!
! template <> struct promote_to_int<bool> { typedef int type; };
! template <> struct promote_to_int<char> { typedef int type; };
! template <> struct promote_to_int<unsigned char> { typedef int type; };
! template <> struct promote_to_int<signed char> { typedef int type; };
! template <> struct promote_to_int<short int> { typedef int type; };
!
! // The unsigned short int promotion rule is this:
! // unsigned short int to signed int if a signed int can hold all values
! // of unsigned short int, otherwise go to unsigned int.
! template <> struct promote_to_int<unsigned short int>
! {
! typedef
! detail::IF<sizeof(int) <= sizeof(unsigned short int),
! // I had the logic reversed but ">" messes up the parsing.
! unsigned int,
! int>::RET type;
! };
!
!
! // TODO: think, should there be default behaviour for non-standard types?
!
! } // namespace detail
!
! // ------------------------------------------
! // Unary actions ----------------------------
! // ------------------------------------------
!
! template<class Act, class A>
! struct plain_return_type_1 {
! typedef detail::unspecified type;
! };
!
!
!
! template<class Act, class A>
! struct plain_return_type_1<unary_arithmetic_action<Act>, A> {
! typedef A type;
! };
!
! template<class Act, class A>
! struct return_type_1<unary_arithmetic_action<Act>, A> {
! typedef
! typename plain_return_type_1<
! unary_arithmetic_action<Act>,
! typename detail::remove_reference_and_cv<A>::type
! >::type type;
! };
!
!
! template<class A>
! struct plain_return_type_1<bitwise_action<not_action>, A> {
! typedef A type;
! };
!
! // bitwise not, operator~()
! template<class A> struct return_type_1<bitwise_action<not_action>, A> {
! typedef
! typename plain_return_type_1<
! bitwise_action<not_action>,
! typename detail::remove_reference_and_cv<A>::type
! >::type type;
! };
!
!
! // prefix increment and decrement operators return
! // their argument by default as a non-const reference
! template<class Act, class A>
! struct plain_return_type_1<pre_increment_decrement_action<Act>, A> {
! typedef A& type;
! };
!
! template<class Act, class A>
! struct return_type_1<pre_increment_decrement_action<Act>, A> {
! typedef
! typename plain_return_type_1<
! pre_increment_decrement_action<Act>,
! typename detail::remove_reference_and_cv<A>::type
! >::type type;
! };
!
! // post decrement just returns the same plain type.
! template<class Act, class A>
! struct plain_return_type_1<post_increment_decrement_action<Act>, A> {
! typedef A type;
! };
!
! template<class Act, class A>
! struct return_type_1<post_increment_decrement_action<Act>, A>
! {
! typedef
! typename plain_return_type_1<
! post_increment_decrement_action<Act>,
! typename detail::remove_reference_and_cv<A>::type
! >::type type;
! };
!
! // logical not, operator!()
! template<class A>
! struct plain_return_type_1<logical_action<not_action>, A> {
! typedef bool type;
! };
!
! template<class A>
! struct return_type_1<logical_action<not_action>, A> {
! typedef
! typename plain_return_type_1<
! logical_action<not_action>,
! typename detail::remove_reference_and_cv<A>::type
! >::type type;
! };
!
! // address of action ---------------------------------------
!
!
! template<class A>
! struct return_type_1<other_action<addressof_action>, A> {
! typedef
! typename plain_return_type_1<
! other_action<addressof_action>,
! typename detail::remove_reference_and_cv<A>::type
! >::type type1;
!
! // If no user defined specialization for A, then return the
! // cv qualified pointer to A
! typedef typename detail::IF<
! boost::is_same<type1, detail::unspecified>::value,
! typename boost::remove_reference<A>::type*,
! type1
! >::RET type;
! };
!
! // contentsof action ------------------------------------
!
! // TODO: this deduction may lead to fail directly,
! // (if A has no specialization for iterator_traits and has no
! // typedef A::reference.
! // There is no easy way around this, cause there doesn't seem to be a way
! // to test whether a class is an iterator or not.
!
! // The default works with std::iterators.
!
! namespace detail {
!
! // A is a nonreference type
! template <class A> struct contentsof_type {
! typedef typename boost::indirect_reference<A>::type type;
! };
!
! // this is since the nullary () in lambda_functor is always instantiated
! template <> struct contentsof_type<null_type> {
! typedef detail::unspecified type;
! };
!
!
! template <class A> struct contentsof_type<const A> {
! typedef typename contentsof_type<A>::type type1;
! // return a reference to the underlying const type
! // the IF is because the A::reference in the primary template could
! // be some class type rather than a real reference, hence
! // we do not want to make it a reference here either
! typedef typename detail::IF<
! is_reference<type1>::value,
! const typename boost::remove_reference<type1>::type &,
! const type1
! >::RET type;
! };
!
! template <class A> struct contentsof_type<volatile A> {
! typedef typename contentsof_type<A>::type type1;
! typedef typename detail::IF<
! is_reference<type1>::value,
! volatile typename boost::remove_reference<type1>::type &,
! volatile type1
! >::RET type;
! };
!
! template <class A> struct contentsof_type<const volatile A> {
! typedef typename contentsof_type<A>::type type1;
! typedef typename detail::IF<
! is_reference<type1>::value,
! const volatile typename boost::remove_reference<type1>::type &,
! const volatile type1
! >::RET type;
! };
!
! // standard iterator traits should take care of the pointer types
! // but just to be on the safe side, we have the specializations here:
! // these work even if A is cv-qualified.
! template <class A> struct contentsof_type<A*> {
! typedef A& type;
! };
! template <class A> struct contentsof_type<A* const> {
! typedef A& type;
! };
! template <class A> struct contentsof_type<A* volatile> {
! typedef A& type;
! };
! template <class A> struct contentsof_type<A* const volatile> {
! typedef A& type;
! };
!
! template<class A, int N> struct contentsof_type<A[N]> {
! typedef A& type;
! };
! template<class A, int N> struct contentsof_type<const A[N]> {
! typedef const A& type;
! };
! template<class A, int N> struct contentsof_type<volatile A[N]> {
! typedef volatile A& type;
! };
! template<class A, int N> struct contentsof_type<const volatile A[N]> {
! typedef const volatile A& type;
! };
!
!
!
!
!
! } // end detail
!
! template<class A>
! struct return_type_1<other_action<contentsof_action>, A> {
!
! typedef
! typename plain_return_type_1<
! other_action<contentsof_action>,
! typename detail::remove_reference_and_cv<A>::type
! >::type type1;
!
! // If no user defined specialization for A, then return the
! // cv qualified pointer to A
! typedef typename
! detail::IF_type<
! boost::is_same<type1, detail::unspecified>::value,
! detail::contentsof_type<
! typename boost::remove_reference<A>::type
! >,
! detail::identity_mapping<type1>
! >::type type;
! };
!
!
! // ------------------------------------------------------------------
! // binary actions ---------------------------------------------------
! // ------------------------------------------------------------------
!
! // here the default case is: no user defined versions:
! template <class Act, class A, class B>
! struct plain_return_type_2 {
! typedef detail::unspecified type;
! };
!
! namespace detail {
!
! // error classes
! class illegal_pointer_arithmetic{};
!
! // pointer arithmetic type deductions ----------------------
! // value = false means that this is not a pointer arithmetic case
! // value = true means, that this can be a pointer arithmetic case, but not necessarily is
! // This means, that for user defined operators for pointer types, say for some operator+(X, *Y),
! // the deductions must be coded at an earliel level (return_type_2).
!
! template<class Act, class A, class B>
! struct pointer_arithmetic_traits { static const bool value = false; };
!
! template<class A, class B>
! struct pointer_arithmetic_traits<plus_action, A, B> {
!
! typedef typename
! array_to_pointer<typename boost::remove_reference<A>::type>::type AP;
! typedef typename
! array_to_pointer<typename boost::remove_reference<B>::type>::type BP;
!
! static const bool is_pointer_A = boost::is_pointer<AP>::value;
! static const bool is_pointer_B = boost::is_pointer<BP>::value;
!
! static const bool value = is_pointer_A || is_pointer_B;
!
! // can't add two pointers.
! // note, that we do not check wether the other type is valid for
! // addition with a pointer.
! // the compiler will catch it in the apply function
!
! typedef typename
! detail::IF<
! is_pointer_A && is_pointer_B,
! detail::return_type_deduction_failure<
! detail::illegal_pointer_arithmetic
! >,
! typename detail::IF<is_pointer_A, AP, BP>::RET
! >::RET type;
!
! };
!
! template<class A, class B>
! struct pointer_arithmetic_traits<minus_action, A, B> {
! typedef typename
! array_to_pointer<typename boost::remove_reference<A>::type>::type AP;
! typedef typename
! array_to_pointer<typename boost::remove_reference<B>::type>::type BP;
!
! static const bool is_pointer_A = boost::is_pointer<AP>::value;
! static const bool is_pointer_B = boost::is_pointer<BP>::value;
!
! static const bool value = is_pointer_A || is_pointer_B;
!
! static const bool same_pointer_type =
! is_pointer_A && is_pointer_B &&
! boost::is_same<
! typename boost::remove_const<
! typename boost::remove_pointer<
! typename boost::remove_const<AP>::type
! >::type
! >::type,
! typename boost::remove_const<
! typename boost::remove_pointer<
! typename boost::remove_const<BP>::type
! >::type
! >::type
! >::value;
!
! // ptr - ptr has type ptrdiff_t
! // note, that we do not check if, in ptr - B, B is
! // valid for subtraction with a pointer.
! // the compiler will catch it in the apply function
!
! typedef typename
! detail::IF<
! same_pointer_type, const std::ptrdiff_t,
! typename detail::IF<
! is_pointer_A,
! AP,
! detail::return_type_deduction_failure<detail::illegal_pointer_arithmetic>
! >::RET
! >::RET type;
! };
!
! } // namespace detail
!
! // -- arithmetic actions ---------------------------------------------
!
! namespace detail {
!
! template<bool is_pointer_arithmetic, class Act, class A, class B>
! struct return_type_2_arithmetic_phase_1;
!
! template<class A, class B> struct return_type_2_arithmetic_phase_2;
! template<class A, class B> struct return_type_2_arithmetic_phase_3;
!
! } // namespace detail
!
!
! // drop any qualifiers from the argument types within arithmetic_action
! template<class A, class B, class Act>
! struct return_type_2<arithmetic_action<Act>, A, B>
! {
! typedef typename detail::remove_reference_and_cv<A>::type plain_A;
! typedef typename detail::remove_reference_and_cv<B>::type plain_B;
!
! typedef typename
! plain_return_type_2<arithmetic_action<Act>, plain_A, plain_B>::type type1;
!
! // if user defined return type, do not enter the whole arithmetic deductions
! typedef typename
! detail::IF_type<
! boost::is_same<type1, detail::unspecified>::value,
! detail::return_type_2_arithmetic_phase_1<
! detail::pointer_arithmetic_traits<Act, A, B>::value, Act, A, B
! >,
! plain_return_type_2<arithmetic_action<Act>, plain_A, plain_B>
! >::type type;
! };
!
! namespace detail {
!
! // perform integral promotion, no pointer arithmetic
! template<bool is_pointer_arithmetic, class Act, class A, class B>
! struct return_type_2_arithmetic_phase_1
! {
! typedef typename
! return_type_2_arithmetic_phase_2<
! typename remove_reference_and_cv<A>::type,
! typename remove_reference_and_cv<B>::type
! >::type type;
! };
!
! // pointer_arithmetic
! template<class Act, class A, class B>
! struct return_type_2_arithmetic_phase_1<true, Act, A, B>
! {
! typedef typename
! pointer_arithmetic_traits<Act, A, B>::type type;
! };
!
! template<class A, class B>
! struct return_type_2_arithmetic_phase_2 {
! typedef typename
! return_type_2_arithmetic_phase_3<
! typename promote_to_int<A>::type,
! typename promote_to_int<B>::type
! >::type type;
! };
!
! // specialization for unsigned int.
! // We only have to do these two specialization because the value promotion will
! // take care of the other cases.
! // The unsigned int promotion rule is this:
! // unsigned int to long if a long can hold all values of unsigned int,
! // otherwise go to unsigned long.
!
! // struct so I don't have to type this twice.
! struct promotion_of_unsigned_int
! {
! typedef
! detail::IF<sizeof(long) <= sizeof(unsigned int),
! unsigned long,
! long>::RET type;
! };
!
! template<>
! struct return_type_2_arithmetic_phase_2<unsigned int, long>
! {
! typedef promotion_of_unsigned_int::type type;
! };
! template<>
! struct return_type_2_arithmetic_phase_2<long, unsigned int>
! {
! typedef promotion_of_unsigned_int::type type;
! };
!
!
! template<class A, class B> struct return_type_2_arithmetic_phase_3 {
! enum { promote_code_A_value = promote_code<A>::value,
! promote_code_B_value = promote_code<B>::value }; // enums for KCC
! typedef typename
! detail::IF<
! promote_code_A_value == -1 || promote_code_B_value == -1,
! detail::return_type_deduction_failure<return_type_2_arithmetic_phase_3>,
! typename detail::IF<
! ((int)promote_code_A_value > (int)promote_code_B_value),
! A,
! B
! >::RET
! >::RET type;
! };
!
! } // namespace detail
!
! // -- bitwise actions -------------------------------------------
! // note: for integral types deuduction is similar to arithmetic actions.
!
! // drop any qualifiers from the argument types within arithmetic action
! template<class A, class B, class Act>
! struct return_type_2<bitwise_action<Act>, A, B>
! {
!
! typedef typename detail::remove_reference_and_cv<A>::type plain_A;
! typedef typename detail::remove_reference_and_cv<B>::type plain_B;
!
! typedef typename
! plain_return_type_2<bitwise_action<Act>, plain_A, plain_B>::type type1;
!
! // if user defined return type, do not enter type deductions
! typedef typename
! detail::IF_type<
! boost::is_same<type1, detail::unspecified>::value,
! return_type_2<arithmetic_action<plus_action>, A, B>,
! plain_return_type_2<bitwise_action<Act>, plain_A, plain_B>
! >::type type;
!
! // plus_action is just a random pick, has to be a concrete instance
!
! // TODO: This check is only valid for built-in types, overloaded types might
! // accept floating point operators
!
! // bitwise operators not defined for floating point types
! // these test are not strictly needed here, since the error will be caught in
! // the apply function
! BOOST_STATIC_ASSERT(!(boost::is_float<plain_A>::value && boost::is_float<plain_B>::value));
!
! };
!
! namespace detail {
!
! #ifdef BOOST_NO_TEMPLATED_STREAMS
!
! template<class A, class B>
! struct leftshift_type {
!
! typedef typename detail::IF<
! boost::is_convertible<
! typename boost::remove_reference<A>::type*,
! std::ostream*
! >::value,
! std::ostream&,
! typename detail::remove_reference_and_cv<A>::type
! >::RET type;
! };
!
! template<class A, class B>
! struct rightshift_type {
!
! typedef typename detail::IF<
!
! boost::is_convertible<
! typename boost::remove_reference<A>::type*,
! std::istream*
! >::value,
! std::istream&,
! typename detail::remove_reference_and_cv<A>::type
! >::RET type;
! };
!
! #else
!
! template <class T> struct get_ostream_type {
! typedef std::basic_ostream<typename T::char_type,
! typename T::traits_type>& type;
! };
!
! template <class T> struct get_istream_type {
! typedef std::basic_istream<typename T::char_type,
! typename T::traits_type>& type;
! };
!
! template<class A, class B>
! struct leftshift_type {
! private:
! typedef typename boost::remove_reference<A>::type plainA;
! public:
! typedef typename detail::IF_type<
! is_instance_of_2<plainA, std::basic_ostream>::value,
! get_ostream_type<plainA>, //reference to the stream
! detail::remove_reference_and_cv<A>
! >::type type;
! };
!
! template<class A, class B>
! struct rightshift_type {
! private:
! typedef typename boost::remove_reference<A>::type plainA;
! public:
! typedef typename detail::IF_type<
! is_instance_of_2<plainA, std::basic_istream>::value,
! get_istream_type<plainA>, //reference to the stream
! detail::remove_reference_and_cv<A>
! >::type type;
! };
!
!
! #endif
!
! } // end detail
!
! // ostream
! template<class A, class B>
! struct return_type_2<bitwise_action<leftshift_action>, A, B>
! {
! typedef typename detail::remove_reference_and_cv<A>::type plain_A;
! typedef typename detail::remove_reference_and_cv<B>::type plain_B;
!
! typedef typename
! plain_return_type_2<bitwise_action<leftshift_action>, plain_A, plain_B>::type type1;
!
! // if user defined return type, do not enter type deductions
! typedef typename
! detail::IF_type<
! boost::is_same<type1, detail::unspecified>::value,
! detail::leftshift_type<A, B>,
! plain_return_type_2<bitwise_action<leftshift_action>, plain_A, plain_B>
! >::type type;
! };
!
! // istream
! template<class A, class B>
! struct return_type_2<bitwise_action<rightshift_action>, A, B>
! {
! typedef typename detail::remove_reference_and_cv<A>::type plain_A;
! typedef typename detail::remove_reference_and_cv<B>::type plain_B;
!
! typedef typename
! plain_return_type_2<bitwise_action<rightshift_action>, plain_A, plain_B>::type type1;
!
! // if user defined return type, do not enter type deductions
! typedef typename
! detail::IF_type<
! boost::is_same<type1, detail::unspecified>::value,
! detail::rightshift_type<A, B>,
! plain_return_type_2<bitwise_action<rightshift_action>, plain_A, plain_B>
! >::type type;
! };
!
! // -- logical actions ----------------------------------------
! // always bool
! // NOTE: this may not be true for some weird user-defined types,
! template<class A, class B, class Act>
! struct plain_return_type_2<logical_action<Act>, A, B> {
! typedef bool type;
! };
!
! template<class A, class B, class Act>
! struct return_type_2<logical_action<Act>, A, B> {
!
! typedef typename detail::remove_reference_and_cv<A>::type plain_A;
! typedef typename detail::remove_reference_and_cv<B>::type plain_B;
!
! typedef typename
! plain_return_type_2<logical_action<Act>, plain_A, plain_B>::type type;
!
! };
!
!
! // -- relational actions ----------------------------------------
! // always bool
! // NOTE: this may not be true for some weird user-defined types,
! template<class A, class B, class Act>
! struct plain_return_type_2<relational_action<Act>, A, B> {
! typedef bool type;
! };
!
! template<class A, class B, class Act>
! struct return_type_2<relational_action<Act>, A, B> {
!
! typedef typename detail::remove_reference_and_cv<A>::type plain_A;
! typedef typename detail::remove_reference_and_cv<B>::type plain_B;
!
! typedef typename
! plain_return_type_2<relational_action<Act>, plain_A, plain_B>::type type;
! };
!
! // Assingment actions -----------------------------------------------
! // return type is the type of the first argument as reference
!
! // note that cv-qualifiers are preserved.
! // Yes, assignment operator can be const!
!
! // NOTE: this may not be true for some weird user-defined types,
!
! template<class A, class B, class Act>
! struct return_type_2<arithmetic_assignment_action<Act>, A, B> {
!
! typedef typename detail::remove_reference_and_cv<A>::type plain_A;
! typedef typename detail::remove_reference_and_cv<B>::type plain_B;
!
! typedef typename
! plain_return_type_2<
! arithmetic_assignment_action<Act>, plain_A, plain_B
! >::type type1;
!
! typedef typename
! detail::IF<
! boost::is_same<type1, detail::unspecified>::value,
! typename boost::add_reference<A>::type,
! type1
! >::RET type;
! };
!
! template<class A, class B, class Act>
! struct return_type_2<bitwise_assignment_action<Act>, A, B> {
!
! typedef typename detail::remove_reference_and_cv<A>::type plain_A;
! typedef typename detail::remove_reference_and_cv<B>::type plain_B;
!
! typedef typename
! plain_return_type_2<
! bitwise_assignment_action<Act>, plain_A, plain_B
! >::type type1;
!
! typedef typename
! detail::IF<
! boost::is_same<type1, detail::unspecified>::value,
! typename boost::add_reference<A>::type,
! type1
! >::RET type;
! };
!
! template<class A, class B>
! struct return_type_2<other_action<assignment_action>, A, B> {
! typedef typename detail::remove_reference_and_cv<A>::type plain_A;
! typedef typename detail::remove_reference_and_cv<B>::type plain_B;
!
! typedef typename
! plain_return_type_2<
! other_action<assignment_action>, plain_A, plain_B
! >::type type1;
!
! typedef typename
! detail::IF<
! boost::is_same<type1, detail::unspecified>::value,
! typename boost::add_reference<A>::type,
! type1
! >::RET type;
! };
!
! // -- other actions ----------------------------------------
!
! // comma action ----------------------------------
! // Note: this may not be true for some weird user-defined types,
!
! // NOTE! This only tries the plain_return_type_2 layer and gives
! // detail::unspecified as default. If no such specialization is found, the
! // type rule in the spcecialization of the return_type_2_prot is used
! // to give the type of the right argument (which can be a reference too)
! // (The built in operator, can return a l- or rvalue).
! template<class A, class B>
! struct return_type_2<other_action<comma_action>, A, B> {
!
! typedef typename detail::remove_reference_and_cv<A>::type plain_A;
! typedef typename detail::remove_reference_and_cv<B>::type plain_B;
!
! typedef typename
! plain_return_type_2<
! other_action<comma_action>, plain_A, plain_B
! >::type type;
! };
!
! // subscript action -----------------------------------------------
!
!
! namespace detail {
! // A and B are nonreference types
! template <class A, class B> struct subscript_type {
! typedef detail::unspecified type;
! };
!
! template <class A, class B> struct subscript_type<A*, B> {
! typedef A& type;
! };
! template <class A, class B> struct subscript_type<A* const, B> {
! typedef A& type;
! };
! template <class A, class B> struct subscript_type<A* volatile, B> {
! typedef A& type;
! };
! template <class A, class B> struct subscript_type<A* const volatile, B> {
! typedef A& type;
! };
!
!
! template<class A, class B, int N> struct subscript_type<A[N], B> {
! typedef A& type;
! };
!
! // these 3 specializations are needed to make gcc <3 happy
! template<class A, class B, int N> struct subscript_type<const A[N], B> {
! typedef const A& type;
! };
! template<class A, class B, int N> struct subscript_type<volatile A[N], B> {
! typedef volatile A& type;
! };
! template<class A, class B, int N> struct subscript_type<const volatile A[N], B> {
! typedef const volatile A& type;
! };
!
! } // end detail
!
! template<class A, class B>
! struct return_type_2<other_action<subscript_action>, A, B> {
!
! typedef typename detail::remove_reference_and_cv<A>::type plain_A;
! typedef typename detail::remove_reference_and_cv<B>::type plain_B;
!
! typedef typename boost::remove_reference<A>::type nonref_A;
! typedef typename boost::remove_reference<B>::type nonref_B;
!
! typedef typename
! plain_return_type_2<
! other_action<subscript_action>, plain_A, plain_B
! >::type type1;
!
! typedef typename
! detail::IF_type<
! boost::is_same<type1, detail::unspecified>::value,
! detail::subscript_type<nonref_A, nonref_B>,
! plain_return_type_2<other_action<subscript_action>, plain_A, plain_B>
! >::type type;
!
! };
!
!
! } // namespace lambda
! } // namespace boost
!
!
! // Forward declarations are incompatible with the libstdc++ debug mode.
! #if BOOST_WORKAROUND(__GNUC__, >= 3) && defined(_GLIBCXX_DEBUG)
! #include <string>
! #include <vector>
! #include <map>
! #include <deque>
! #else
!
! // The GCC 2.95.x uses a non-conformant deque
! #if BOOST_WORKAROUND(__GNUC__, == 2) && __GNUC_MINOR__ <= 96
! #include <deque>
! #else
!
! namespace std {
! template <class T, class Allocator> class deque;
! }
!
! #endif
!
! namespace std {
! template <class Char, class Traits, class Allocator> class basic_string;
! template <class T, class Allocator> class vector;
! template <class Key, class T, class Cmp, class Allocator> class map;
! template <class Key, class T, class Cmp, class Allocator> class multimap;
! }
!
! #endif
!
!
!
! namespace boost {
! namespace lambda {
!
! template<class Key, class T, class Cmp, class Allocator, class B>
! struct plain_return_type_2<other_action<subscript_action>, std::map<Key, T, Cmp, Allocator>, B> {
! typedef T& type;
! // T == std::map<Key, T, Cmp, Allocator>::mapped_type;
! };
!
! template<class Key, class T, class Cmp, class Allocator, class B>
! struct plain_return_type_2<other_action<subscript_action>, std::multimap<Key, T, Cmp, Allocator>, B> {
! typedef T& type;
! // T == std::map<Key, T, Cmp, Allocator>::mapped_type;
! };
!
! // deque
! template<class T, class Allocator, class B>
! struct plain_return_type_2<other_action<subscript_action>, std::deque<T, Allocator>, B> {
! typedef typename std::deque<T, Allocator>::reference type;
! };
! template<class T, class Allocator, class B>
! struct plain_return_type_2<other_action<subscript_action>, const std::deque<T, Allocator>, B> {
! typedef typename std::deque<T, Allocator>::const_reference type;
! };
!
! // vector
! template<class T, class Allocator, class B>
! struct plain_return_type_2<other_action<subscript_action>, std::vector<T, Allocator>, B> {
! typedef typename std::vector<T, Allocator>::reference type;
! };
! template<class T, class Allocator, class B>
! struct plain_return_type_2<other_action<subscript_action>, const std::vector<T, Allocator>, B> {
! typedef typename std::vector<T, Allocator>::const_reference type;
! };
!
! // basic_string
! template<class Char, class Traits, class Allocator, class B>
! struct plain_return_type_2<other_action<subscript_action>, std::basic_string<Char, Traits, Allocator>, B> {
! typedef typename std::basic_string<Char, Traits, Allocator>::reference type;
! };
! template<class Char, class Traits, class Allocator, class B>
! struct plain_return_type_2<other_action<subscript_action>, const std::basic_string<Char, Traits, Allocator>, B> {
! typedef typename std::basic_string<Char, Traits, Allocator>::const_reference type;
! };
!
!
! } // namespace lambda
! } // namespace boost
!
! #endif
!
!
--- 1,1004 ----
! // operator_return_type_traits.hpp -- Boost Lambda Library ------------------
!
! // Copyright (C) 1999, 2000 Jaakko Järvi (jaakko.jarvi_at_[hidden])
! //
! // 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
!
! #ifndef BOOST_LAMBDA_OPERATOR_RETURN_TYPE_TRAITS_HPP
! #define BOOST_LAMBDA_OPERATOR_RETURN_TYPE_TRAITS_HPP
!
! #include "boost/lambda/detail/is_instance_of.hpp"
! #include "boost/type_traits/same_traits.hpp"
! #include "boost/type_traits/cv_traits.hpp"
! #include "boost/type_traits/remove_reference.hpp"
!
! #include "boost/indirect_reference.hpp"
!
! #include <cstddef> // needed for the ptrdiff_t
! #include <iosfwd> // for istream and ostream
!
! #include <iterator> // needed for operator&
!
! namespace boost {
! namespace lambda {
! namespace detail {
!
! // -- general helper templates for type deduction ------------------
!
! // Much of the type deduction code for standard arithmetic types from Gary Powell
!
! template <class A> struct promote_code { static const int value = -1; };
! // this means that a code is not defined for A
!
! // -- the next 5 types are needed in if_then_else_return
! // the promotion order is not important, but they must have distinct values.
! template <> struct promote_code<bool> { static const int value = 10; };
! template <> struct promote_code<char> { static const int value = 20; };
! template <> struct promote_code<unsigned char> { static const int value = 30; };
! template <> struct promote_code<signed char> { static const int value = 40; };
! template <> struct promote_code<short int> { static const int value = 50; };
! // ----------
!
! template <> struct promote_code<int> { static const int value = 100; };
! template <> struct promote_code<unsigned int> { static const int value = 200; };
! template <> struct promote_code<long> { static const int value = 300; };
! template <> struct promote_code<unsigned long> { static const int value = 400; };
!
! template <> struct promote_code<float> { static const int value = 500; };
! template <> struct promote_code<double> { static const int value = 600; };
! template <> struct promote_code<long double> { static const int value = 700; };
!
! // TODO: wchar_t
!
! // forward delcaration of complex.
!
! } // namespace detail
! } // namespace lambda
! } // namespace boost
!
! namespace std {
! template<class T> class complex;
! }
!
! namespace boost {
! namespace lambda {
! namespace detail {
!
! template <> struct promote_code< std::complex<float> > { static const int value = 800; };
! template <> struct promote_code< std::complex<double> > { static const int value = 900; };
! template <> struct promote_code< std::complex<long double> > { static const int value = 1000; };
!
! // -- int promotion -------------------------------------------
! template <class T> struct promote_to_int { typedef T type; };
!
! template <> struct promote_to_int<bool> { typedef int type; };
! template <> struct promote_to_int<char> { typedef int type; };
! template <> struct promote_to_int<unsigned char> { typedef int type; };
! template <> struct promote_to_int<signed char> { typedef int type; };
! template <> struct promote_to_int<short int> { typedef int type; };
!
! // The unsigned short int promotion rule is this:
! // unsigned short int to signed int if a signed int can hold all values
! // of unsigned short int, otherwise go to unsigned int.
! template <> struct promote_to_int<unsigned short int>
! {
! typedef
! detail::IF<sizeof(int) <= sizeof(unsigned short int),
! // I had the logic reversed but ">" messes up the parsing.
! unsigned int,
! int>::RET type;
! };
!
!
! // TODO: think, should there be default behaviour for non-standard types?
!
! } // namespace detail
!
! // ------------------------------------------
! // Unary actions ----------------------------
! // ------------------------------------------
!
! template<class Act, class A>
! struct plain_return_type_1 {
! typedef typename detail::IF_type<(is_const<A>::value || is_volatile<A>::value),
! plain_return_type_1<Act, typename remove_cv<A>::type>,
! detail::identity_mapping<detail::unspecified>
! >::type type;
! };
!
!
!
! template<class Act, class A>
! struct plain_return_type_1<unary_arithmetic_action<Act>, A> {
! typedef A type;
! };
!
! template<class Act, class A>
! struct return_type_1<unary_arithmetic_action<Act>, A> {
! typedef
! typename plain_return_type_1<
! unary_arithmetic_action<Act>,
! typename boost::remove_reference<A>::type
! >::type type;
! };
!
!
! template<class A>
! struct plain_return_type_1<bitwise_action<not_action>, A> {
! typedef A type;
! };
!
! // bitwise not, operator~()
! template<class A> struct return_type_1<bitwise_action<not_action>, A> {
! typedef
! typename plain_return_type_1<
! bitwise_action<not_action>,
! typename boost::remove_reference<A>::type
! >::type type;
! };
!
!
! // prefix increment and decrement operators return
! // their argument by default as a non-const reference
! template<class Act, class A>
! struct plain_return_type_1<pre_increment_decrement_action<Act>, A> {
! typedef A& type;
! };
!
! template<class Act, class A>
! struct return_type_1<pre_increment_decrement_action<Act>, A> {
! typedef
! typename plain_return_type_1<
! pre_increment_decrement_action<Act>,
! typename boost::remove_reference<A>::type
! >::type type;
! };
!
! // post decrement just returns the same plain type.
! template<class Act, class A>
! struct plain_return_type_1<post_increment_decrement_action<Act>, A> {
! typedef A type;
! };
!
! template<class Act, class A>
! struct return_type_1<post_increment_decrement_action<Act>, A>
! {
! typedef
! typename plain_return_type_1<
! post_increment_decrement_action<Act>,
! typename boost::remove_reference<A>::type
! >::type type;
! };
!
! // logical not, operator!()
! template<class A>
! struct plain_return_type_1<logical_action<not_action>, A> {
! typedef bool type;
! };
!
! template<class A>
! struct return_type_1<logical_action<not_action>, A> {
! typedef
! typename plain_return_type_1<
! logical_action<not_action>,
! typename boost::remove_reference<A>::type
! >::type type;
! };
!
! // address of action ---------------------------------------
!
!
! template<class A>
! struct return_type_1<other_action<addressof_action>, A> {
! typedef
! typename plain_return_type_1<
! other_action<addressof_action>,
! typename boost::remove_reference<A>::type
! >::type type1;
!
! // If no user defined specialization for A, then return the
! // cv qualified pointer to A
! typedef typename detail::IF<
! boost::is_same<type1, detail::unspecified>::value,
! typename boost::remove_reference<A>::type*,
! type1
! >::RET type;
! };
!
! // contentsof action ------------------------------------
!
! // TODO: this deduction may lead to fail directly,
! // (if A has no specialization for iterator_traits and has no
! // typedef A::reference.
! // There is no easy way around this, cause there doesn't seem to be a way
! // to test whether a class is an iterator or not.
!
! // The default works with std::iterators.
!
! namespace detail {
!
! // A is a nonreference type
! template <class A> struct contentsof_type {
! typedef typename boost::indirect_reference<A>::type type;
! };
!
! // this is since the nullary () in lambda_functor is always instantiated
! template <> struct contentsof_type<null_type> {
! typedef detail::unspecified type;
! };
!
!
! template <class A> struct contentsof_type<const A> {
! typedef typename contentsof_type<A>::type type1;
! // return a reference to the underlying const type
! // the IF is because the A::reference in the primary template could
! // be some class type rather than a real reference, hence
! // we do not want to make it a reference here either
! typedef typename detail::IF<
! is_reference<type1>::value,
! const typename boost::remove_reference<type1>::type &,
! const type1
! >::RET type;
! };
!
! template <class A> struct contentsof_type<volatile A> {
! typedef typename contentsof_type<A>::type type1;
! typedef typename detail::IF<
! is_reference<type1>::value,
! volatile typename boost::remove_reference<type1>::type &,
! volatile type1
! >::RET type;
! };
!
! template <class A> struct contentsof_type<const volatile A> {
! typedef typename contentsof_type<A>::type type1;
! typedef typename detail::IF<
! is_reference<type1>::value,
! const volatile typename boost::remove_reference<type1>::type &,
! const volatile type1
! >::RET type;
! };
!
! // standard iterator traits should take care of the pointer types
! // but just to be on the safe side, we have the specializations here:
! // these work even if A is cv-qualified.
! template <class A> struct contentsof_type<A*> {
! typedef A& type;
! };
! template <class A> struct contentsof_type<A* const> {
! typedef A& type;
! };
! template <class A> struct contentsof_type<A* volatile> {
! typedef A& type;
! };
! template <class A> struct contentsof_type<A* const volatile> {
! typedef A& type;
! };
!
! template<class A, int N> struct contentsof_type<A[N]> {
! typedef A& type;
! };
! template<class A, int N> struct contentsof_type<const A[N]> {
! typedef const A& type;
! };
! template<class A, int N> struct contentsof_type<volatile A[N]> {
! typedef volatile A& type;
! };
! template<class A, int N> struct contentsof_type<const volatile A[N]> {
! typedef const volatile A& type;
! };
!
!
!
!
!
! } // end detail
!
! template<class A>
! struct return_type_1<other_action<contentsof_action>, A> {
!
! typedef
! typename plain_return_type_1<
! other_action<contentsof_action>,
! typename boost::remove_reference<A>::type
! >::type type1;
!
! // If no user defined specialization for A, then return the
! // cv qualified pointer to A
! typedef typename
! detail::IF_type<
! boost::is_same<type1, detail::unspecified>::value,
! detail::contentsof_type<
! typename boost::remove_reference<A>::type
! >,
! detail::identity_mapping<type1>
! >::type type;
! };
!
!
! // ------------------------------------------------------------------
! // binary actions ---------------------------------------------------
! // ------------------------------------------------------------------
!
! // here the default case is: no user defined versions:
! template <class Act, class A, class B>
! struct plain_return_type_2 {
! typedef typename detail::IF_type<(is_const<A>::value || is_volatile<A>::value || is_const<B>::value || is_volatile<B>::value),
! plain_return_type_2<Act, typename remove_cv<A>::type, typename remove_cv<B>::type>,
! detail::identity_mapping<detail::unspecified>
! >::type type;
! };
!
! namespace detail {
!
! // error classes
! class illegal_pointer_arithmetic{};
!
! // pointer arithmetic type deductions ----------------------
! // value = false means that this is not a pointer arithmetic case
! // value = true means, that this can be a pointer arithmetic case, but not necessarily is
! // This means, that for user defined operators for pointer types, say for some operator+(X, *Y),
! // the deductions must be coded at an earliel level (return_type_2).
!
! template<class Act, class A, class B>
! struct pointer_arithmetic_traits { static const bool value = false; };
!
! template<class A, class B>
! struct pointer_arithmetic_traits<plus_action, A, B> {
!
! typedef typename
! array_to_pointer<typename boost::remove_reference<A>::type>::type AP;
! typedef typename
! array_to_pointer<typename boost::remove_reference<B>::type>::type BP;
!
! static const bool is_pointer_A = boost::is_pointer<AP>::value;
! static const bool is_pointer_B = boost::is_pointer<BP>::value;
!
! static const bool value = is_pointer_A || is_pointer_B;
!
! // can't add two pointers.
! // note, that we do not check wether the other type is valid for
! // addition with a pointer.
! // the compiler will catch it in the apply function
!
! typedef typename
! detail::IF<
! is_pointer_A && is_pointer_B,
! detail::return_type_deduction_failure<
! detail::illegal_pointer_arithmetic
! >,
! typename detail::IF<is_pointer_A, AP, BP>::RET
! >::RET type;
!
! };
!
! template<class A, class B>
! struct pointer_arithmetic_traits<minus_action, A, B> {
! typedef typename
! array_to_pointer<typename boost::remove_reference<A>::type>::type AP;
! typedef typename
! array_to_pointer<typename boost::remove_reference<B>::type>::type BP;
!
! static const bool is_pointer_A = boost::is_pointer<AP>::value;
! static const bool is_pointer_B = boost::is_pointer<BP>::value;
!
! static const bool value = is_pointer_A || is_pointer_B;
!
! static const bool same_pointer_type =
! is_pointer_A && is_pointer_B &&
! boost::is_same<
! typename boost::remove_const<
! typename boost::remove_pointer<
! typename boost::remove_const<AP>::type
! >::type
! >::type,
! typename boost::remove_const<
! typename boost::remove_pointer<
! typename boost::remove_const<BP>::type
! >::type
! >::type
! >::value;
!
! // ptr - ptr has type ptrdiff_t
! // note, that we do not check if, in ptr - B, B is
! // valid for subtraction with a pointer.
! // the compiler will catch it in the apply function
!
! typedef typename
! detail::IF<
! same_pointer_type, const std::ptrdiff_t,
! typename detail::IF<
! is_pointer_A,
! AP,
! detail::return_type_deduction_failure<detail::illegal_pointer_arithmetic>
! >::RET
! >::RET type;
! };
!
! } // namespace detail
!
! // -- arithmetic actions ---------------------------------------------
!
! namespace detail {
!
! template<bool is_pointer_arithmetic, class Act, class A, class B>
! struct return_type_2_arithmetic_phase_1;
!
! template<class A, class B> struct return_type_2_arithmetic_phase_2;
! template<class A, class B> struct return_type_2_arithmetic_phase_3;
!
! } // namespace detail
!
!
! // drop any qualifiers from the argument types within arithmetic_action
! template<class A, class B, class Act>
! struct return_type_2<arithmetic_action<Act>, A, B>
! {
! typedef typename remove_reference<A>::type plain_A;
! typedef typename remove_reference<B>::type plain_B;
!
! typedef typename
! plain_return_type_2<arithmetic_action<Act>, plain_A, plain_B>::type type1;
!
! // if user defined return type, do not enter the whole arithmetic deductions
! typedef typename
! detail::IF_type<
! boost::is_same<type1, detail::unspecified>::value,
! detail::return_type_2_arithmetic_phase_1<
! detail::pointer_arithmetic_traits<Act, A, B>::value, Act, A, B
! >,
! plain_return_type_2<arithmetic_action<Act>, plain_A, plain_B>
! >::type type;
! };
!
! namespace detail {
!
! // perform integral promotion, no pointer arithmetic
! template<bool is_pointer_arithmetic, class Act, class A, class B>
! struct return_type_2_arithmetic_phase_1
! {
! typedef typename
! return_type_2_arithmetic_phase_2<
! typename remove_reference_and_cv<A>::type,
! typename remove_reference_and_cv<B>::type
! >::type type;
! };
!
! // pointer_arithmetic
! template<class Act, class A, class B>
! struct return_type_2_arithmetic_phase_1<true, Act, A, B>
! {
! typedef typename
! pointer_arithmetic_traits<Act, A, B>::type type;
! };
!
! template<class A, class B>
! struct return_type_2_arithmetic_phase_2 {
! typedef typename
! return_type_2_arithmetic_phase_3<
! typename promote_to_int<A>::type,
! typename promote_to_int<B>::type
! >::type type;
! };
!
! // specialization for unsigned int.
! // We only have to do these two specialization because the value promotion will
! // take care of the other cases.
! // The unsigned int promotion rule is this:
! // unsigned int to long if a long can hold all values of unsigned int,
! // otherwise go to unsigned long.
!
! // struct so I don't have to type this twice.
! struct promotion_of_unsigned_int
! {
! typedef
! detail::IF<sizeof(long) <= sizeof(unsigned int),
! unsigned long,
! long>::RET type;
! };
!
! template<>
! struct return_type_2_arithmetic_phase_2<unsigned int, long>
! {
! typedef promotion_of_unsigned_int::type type;
! };
! template<>
! struct return_type_2_arithmetic_phase_2<long, unsigned int>
! {
! typedef promotion_of_unsigned_int::type type;
! };
!
!
! template<class A, class B> struct return_type_2_arithmetic_phase_3 {
! enum { promote_code_A_value = promote_code<A>::value,
! promote_code_B_value = promote_code<B>::value }; // enums for KCC
! typedef typename
! detail::IF<
! promote_code_A_value == -1 || promote_code_B_value == -1,
! detail::return_type_deduction_failure<return_type_2_arithmetic_phase_3>,
! typename detail::IF<
! ((int)promote_code_A_value > (int)promote_code_B_value),
! A,
! B
! >::RET
! >::RET type;
! };
!
! } // namespace detail
!
! // -- bitwise actions -------------------------------------------
! // note: for integral types deuduction is similar to arithmetic actions.
!
! // drop any qualifiers from the argument types within arithmetic action
! template<class A, class B, class Act>
! struct return_type_2<bitwise_action<Act>, A, B>
! {
!
! typedef typename boost::remove_reference<A>::type plain_A;
! typedef typename boost::remove_reference<B>::type plain_B;
!
! typedef typename
! plain_return_type_2<bitwise_action<Act>, plain_A, plain_B>::type type1;
!
! // if user defined return type, do not enter type deductions
! typedef typename
! detail::IF_type<
! boost::is_same<type1, detail::unspecified>::value,
! return_type_2<arithmetic_action<plus_action>, A, B>,
! plain_return_type_2<bitwise_action<Act>, plain_A, plain_B>
! >::type type;
!
! // plus_action is just a random pick, has to be a concrete instance
!
! // TODO: This check is only valid for built-in types, overloaded types might
! // accept floating point operators
!
! // bitwise operators not defined for floating point types
! // these test are not strictly needed here, since the error will be caught in
! // the apply function
! BOOST_STATIC_ASSERT(!(boost::is_float<plain_A>::value && boost::is_float<plain_B>::value));
!
! };
!
! namespace detail {
!
! #ifdef BOOST_NO_TEMPLATED_STREAMS
!
! template<class A, class B>
! struct leftshift_type {
!
! typedef typename detail::IF<
! boost::is_convertible<
! typename boost::remove_reference<A>::type*,
! std::ostream*
! >::value,
! std::ostream&,
! typename detail::remove_reference_and_cv<A>::type
! >::RET type;
! };
!
! template<class A, class B>
! struct rightshift_type {
!
! typedef typename detail::IF<
!
! boost::is_convertible<
! typename boost::remove_reference<A>::type*,
! std::istream*
! >::value,
! std::istream&,
! typename detail::remove_reference_and_cv<A>::type
! >::RET type;
! };
!
! #else
!
! template <class T> struct get_ostream_type {
! typedef std::basic_ostream<typename T::char_type,
! typename T::traits_type>& type;
! };
!
! template <class T> struct get_istream_type {
! typedef std::basic_istream<typename T::char_type,
! typename T::traits_type>& type;
! };
!
! template<class A, class B>
! struct leftshift_type {
! private:
! typedef typename boost::remove_reference<A>::type plainA;
! public:
! typedef typename detail::IF_type<
! is_instance_of_2<plainA, std::basic_ostream>::value,
! get_ostream_type<plainA>, //reference to the stream
! detail::remove_reference_and_cv<A>
! >::type type;
! };
!
! template<class A, class B>
! struct rightshift_type {
! private:
! typedef typename boost::remove_reference<A>::type plainA;
! public:
! typedef typename detail::IF_type<
! is_instance_of_2<plainA, std::basic_istream>::value,
! get_istream_type<plainA>, //reference to the stream
! detail::remove_reference_and_cv<A>
! >::type type;
! };
!
!
! #endif
!
! } // end detail
!
! // ostream
! template<class A, class B>
! struct return_type_2<bitwise_action<leftshift_action>, A, B>
! {
! typedef typename boost::remove_reference<A>::type plain_A;
! typedef typename boost::remove_reference<B>::type plain_B;
!
! typedef typename
! plain_return_type_2<bitwise_action<leftshift_action>, plain_A, plain_B>::type type1;
!
! // if user defined return type, do not enter type deductions
! typedef typename
! detail::IF_type<
! boost::is_same<type1, detail::unspecified>::value,
! detail::leftshift_type<A, B>,
! plain_return_type_2<bitwise_action<leftshift_action>, plain_A, plain_B>
! >::type type;
! };
!
! // istream
! template<class A, class B>
! struct return_type_2<bitwise_action<rightshift_action>, A, B>
! {
! typedef typename boost::remove_reference<A>::type plain_A;
! typedef typename boost::remove_reference<B>::type plain_B;
!
! typedef typename
! plain_return_type_2<bitwise_action<rightshift_action>, plain_A, plain_B>::type type1;
!
! // if user defined return type, do not enter type deductions
! typedef typename
! detail::IF_type<
! boost::is_same<type1, detail::unspecified>::value,
! detail::rightshift_type<A, B>,
! plain_return_type_2<bitwise_action<rightshift_action>, plain_A, plain_B>
! >::type type;
! };
!
! // -- logical actions ----------------------------------------
! // always bool
! // NOTE: this may not be true for some weird user-defined types,
! template<class A, class B, class Act>
! struct plain_return_type_2<logical_action<Act>, A, B> {
! typedef bool type;
! };
!
! template<class A, class B, class Act>
! struct return_type_2<logical_action<Act>, A, B> {
!
! typedef typename boost::remove_reference<A>::type plain_A;
! typedef typename boost::remove_reference<B>::type plain_B;
!
! typedef typename
! plain_return_type_2<logical_action<Act>, plain_A, plain_B>::type type;
!
! };
!
!
! // -- relational actions ----------------------------------------
! // always bool
! // NOTE: this may not be true for some weird user-defined types,
! template<class A, class B, class Act>
! struct plain_return_type_2<relational_action<Act>, A, B> {
! typedef bool type;
! };
!
! template<class A, class B, class Act>
! struct return_type_2<relational_action<Act>, A, B> {
!
! typedef typename boost::remove_reference<A>::type plain_A;
! typedef typename boost::remove_reference<B>::type plain_B;
!
! typedef typename
! plain_return_type_2<relational_action<Act>, plain_A, plain_B>::type type;
! };
!
! // Assingment actions -----------------------------------------------
! // return type is the type of the first argument as reference
!
! // note that cv-qualifiers are preserved.
! // Yes, assignment operator can be const!
!
! // NOTE: this may not be true for some weird user-defined types,
!
! template<class A, class B, class Act>
! struct return_type_2<arithmetic_assignment_action<Act>, A, B> {
!
! typedef typename boost::remove_reference<A>::type plain_A;
! typedef typename boost::remove_reference<B>::type plain_B;
!
! typedef typename
! plain_return_type_2<
! arithmetic_assignment_action<Act>, plain_A, plain_B
! >::type type1;
!
! typedef typename
! detail::IF<
! boost::is_same<type1, detail::unspecified>::value,
! typename boost::add_reference<A>::type,
! type1
! >::RET type;
! };
!
! template<class A, class B, class Act>
! struct return_type_2<bitwise_assignment_action<Act>, A, B> {
!
! typedef typename boost::remove_reference<A>::type plain_A;
! typedef typename boost::remove_reference<B>::type plain_B;
!
! typedef typename
! plain_return_type_2<
! bitwise_assignment_action<Act>, plain_A, plain_B
! >::type type1;
!
! typedef typename
! detail::IF<
! boost::is_same<type1, detail::unspecified>::value,
! typename boost::add_reference<A>::type,
! type1
! >::RET type;
! };
!
! template<class A, class B>
! struct return_type_2<other_action<assignment_action>, A, B> {
! typedef typename boost::remove_reference<A>::type plain_A;
! typedef typename boost::remove_reference<B>::type plain_B;
!
! typedef typename
! plain_return_type_2<
! other_action<assignment_action>, plain_A, plain_B
! >::type type1;
!
! typedef typename
! detail::IF<
! boost::is_same<type1, detail::unspecified>::value,
! typename boost::add_reference<A>::type,
! type1
! >::RET type;
! };
!
! // -- other actions ----------------------------------------
!
! // comma action ----------------------------------
! // Note: this may not be true for some weird user-defined types,
!
! // NOTE! This only tries the plain_return_type_2 layer and gives
! // detail::unspecified as default. If no such specialization is found, the
! // type rule in the spcecialization of the return_type_2_prot is used
! // to give the type of the right argument (which can be a reference too)
! // (The built in operator, can return a l- or rvalue).
! template<class A, class B>
! struct return_type_2<other_action<comma_action>, A, B> {
!
! typedef typename remove_reference<A>::type plain_A;
! typedef typename remove_reference<B>::type plain_B;
!
! typedef typename
! plain_return_type_2<
! other_action<comma_action>, plain_A, plain_B
! >::type type;
! };
!
! // subscript action -----------------------------------------------
!
!
! namespace detail {
! // A and B are nonreference types
! template <class A, class B> struct subscript_type {
! typedef detail::unspecified type;
! };
!
! template <class A, class B> struct subscript_type<A*, B> {
! typedef A& type;
! };
! template <class A, class B> struct subscript_type<A* const, B> {
! typedef A& type;
! };
! template <class A, class B> struct subscript_type<A* volatile, B> {
! typedef A& type;
! };
! template <class A, class B> struct subscript_type<A* const volatile, B> {
! typedef A& type;
! };
!
!
! template<class A, class B, int N> struct subscript_type<A[N], B> {
! typedef A& type;
! };
!
! // these 3 specializations are needed to make gcc <3 happy
! template<class A, class B, int N> struct subscript_type<const A[N], B> {
! typedef const A& type;
! };
! template<class A, class B, int N> struct subscript_type<volatile A[N], B> {
! typedef volatile A& type;
! };
! template<class A, class B, int N> struct subscript_type<const volatile A[N], B> {
! typedef const volatile A& type;
! };
!
! } // end detail
!
! template<class A, class B>
! struct return_type_2<other_action<subscript_action>, A, B> {
!
! typedef typename remove_reference<A>::type plain_A;
! typedef typename remove_reference<B>::type plain_B;
!
! typedef typename boost::remove_reference<A>::type nonref_A;
! typedef typename boost::remove_reference<B>::type nonref_B;
!
! typedef typename
! plain_return_type_2<
! other_action<subscript_action>, plain_A, plain_B
! >::type type1;
!
! typedef typename
! detail::IF_type<
! boost::is_same<type1, detail::unspecified>::value,
! detail::subscript_type<nonref_A, nonref_B>,
! plain_return_type_2<other_action<subscript_action>, plain_A, plain_B>
! >::type type;
!
! };
!
!
! } // namespace lambda
! } // namespace boost
!
!
! // Forward declarations are incompatible with the libstdc++ debug mode.
! #if BOOST_WORKAROUND(__GNUC__, >= 3) && defined(_GLIBCXX_DEBUG)
! #include <string>
! #include <vector>
! #include <map>
! #include <deque>
! #else
!
! // The GCC 2.95.x uses a non-conformant deque
! #if BOOST_WORKAROUND(__GNUC__, == 2) && __GNUC_MINOR__ <= 96
! #include <deque>
! #else
!
! namespace std {
! template <class T, class Allocator> class deque;
! }
!
! #endif
!
! namespace std {
! template <class Char, class Traits, class Allocator> class basic_string;
! template <class T, class Allocator> class vector;
! template <class Key, class T, class Cmp, class Allocator> class map;
! template <class Key, class T, class Cmp, class Allocator> class multimap;
! }
!
! #endif
!
!
! namespace boost {
! template <class T, std::size_t N> class array;
! }
!
!
! namespace boost {
! namespace lambda {
!
! template<class Key, class T, class Cmp, class Allocator, class B>
! struct plain_return_type_2<other_action<subscript_action>, std::map<Key, T, Cmp, Allocator>, B> {
! typedef T& type;
! // T == std::map<Key, T, Cmp, Allocator>::mapped_type;
! };
!
! template<class Key, class T, class Cmp, class Allocator, class B>
! struct plain_return_type_2<other_action<subscript_action>, std::multimap<Key, T, Cmp, Allocator>, B> {
! typedef T& type;
! // T == std::map<Key, T, Cmp, Allocator>::mapped_type;
! };
!
! // deque
! template<class T, class Allocator, class B>
! struct plain_return_type_2<other_action<subscript_action>, std::deque<T, Allocator>, B> {
! typedef typename std::deque<T, Allocator>::reference type;
! };
! template<class T, class Allocator, class B>
! struct plain_return_type_2<other_action<subscript_action>, const std::deque<T, Allocator>, B> {
! typedef typename std::deque<T, Allocator>::const_reference type;
! };
!
! // vector
! template<class T, class Allocator, class B>
! struct plain_return_type_2<other_action<subscript_action>, std::vector<T, Allocator>, B> {
! typedef typename std::vector<T, Allocator>::reference type;
! };
! template<class T, class Allocator, class B>
! struct plain_return_type_2<other_action<subscript_action>, const std::vector<T, Allocator>, B> {
! typedef typename std::vector<T, Allocator>::const_reference type;
! };
!
! // basic_string
! template<class Char, class Traits, class Allocator, class B>
! struct plain_return_type_2<other_action<subscript_action>, std::basic_string<Char, Traits, Allocator>, B> {
! typedef typename std::basic_string<Char, Traits, Allocator>::reference type;
! };
! template<class Char, class Traits, class Allocator, class B>
! struct plain_return_type_2<other_action<subscript_action>, const std::basic_string<Char, Traits, Allocator>, B> {
! typedef typename std::basic_string<Char, Traits, Allocator>::const_reference type;
! };
!
! template<class T, int N, class B>
! struct return_type_2<other_action<subscript_action>, boost::array<T, N>, B> {
! typedef typename boost::array<T, N>::reference type;
! };
! template<class T, int N, class B>
! struct return_type_2<other_action<subscript_action>, const boost::array<T, N>, B> {
! typedef typename boost::array<T, N>::const_reference type;
! };
!
!
! // -- plus_action for basic_string -----------------------------------------------------------------
! template<class Char, class Traits>
! struct plain_return_type_2<arithmetic_action<plus_action>, std::basic_string<Char, Traits>, std::basic_string<Char, Traits> > {
! typedef std::basic_string<Char, Traits> type;
! };
! // -- pointer versions -----------------------------------------------------------------------------
! template<class Char, class Traits>
! struct plain_return_type_2<arithmetic_action<plus_action>, std::basic_string<Char, Traits>, Char*> {
! typedef std::basic_string<Char, Traits> type;
! };
! template<class Char, class Traits>
! struct plain_return_type_2<arithmetic_action<plus_action>, std::basic_string<Char, Traits>, const Char*> {
! typedef std::basic_string<Char, Traits> type;
! };
! template<class Char, class Traits>
! struct plain_return_type_2<Char*, arithmetic_action<plus_action>, std::basic_string<Char, Traits> > {
! typedef std::basic_string<Char, Traits> type;
! };
! template<class Char, class Traits>
! struct plain_return_type_2<const Char*, arithmetic_action<plus_action>, std::basic_string<Char, Traits> > {
! typedef std::basic_string<Char, Traits> type;
! };
! // -- array versions ---------------------------------------------------------------------------------
! template<class Char, class Traits, int N>
! struct plain_return_type_2<arithmetic_action<plus_action>, std::basic_string<Char, Traits>, Char[N]> {
! typedef std::basic_string<Char, Traits> type;
! };
! template<class Char, class Traits, int N>
! struct plain_return_type_2<arithmetic_action<plus_action>, std::basic_string<Char, Traits>, const Char[N]> {
! typedef std::basic_string<Char, Traits> type;
! };
! template<class Char, class Traits, int N>
! struct plain_return_type_2<Char[N], arithmetic_action<plus_action>, std::basic_string<Char, Traits> > {
! typedef std::basic_string<Char, Traits> type;
! };
! template<class Char, class Traits, int N>
! struct plain_return_type_2<const Char[N], arithmetic_action<plus_action>, std::basic_string<Char, Traits> > {
! typedef std::basic_string<Char, Traits> type;
! };
!
!
! } // namespace lambda
! } // namespace boost
!
! #endif
!
!


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk