diff --git a/include/boost/lambda/detail/operator_return_type_traits.hpp b/include/boost/lambda/detail/operator_return_type_traits.hpp index 4eba43e..402ee4b 100644 --- a/include/boost/lambda/detail/operator_return_type_traits.hpp +++ b/include/boost/lambda/detail/operator_return_type_traits.hpp @@ -16,6 +16,7 @@ #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 // needed for the ptrdiff_t @@ -102,12 +103,16 @@ template <> struct promote_to_int template struct return_type_1, A> { - typedef typename boost::remove_reference::type type; + typedef typename boost::remove_const< + typename boost::remove_reference::type + >::type type; }; // bitwise not, operator~() template struct return_type_1, A> { - typedef typename boost::remove_reference::type type; + typedef typename boost::remove_const< + typename boost::remove_reference::type + >::type type; }; // identity_action @@ -130,11 +135,14 @@ struct return_type_1, A> { }; -// post decrement just returns the same plain stype. +// post decrement just returns the same plain type. template struct return_type_1, A> { - typedef typename boost::remove_reference::type type; + typedef + typename boost::remove_const< + typename boost::remove_reference::type + >::type type; }; // logical not, operator!() @@ -145,7 +153,7 @@ struct return_type_1, A> { // address of action --------------------------------------- // Note that this applies to all types. -// A special user defined & may need to define its own +// A special user defined operator& may need to define its own // specializations template struct return_type_1, A> { @@ -154,14 +162,18 @@ struct return_type_1, A> { // contentsof action ------------------------------------ -// TODO: this deduction may lead to fail directly, gotta find a way -// around it. Specializations for standard iterator types? +// 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. +// (it ain't easy to provide pecializations for just iterator types?) -// default is to assume that a typedef reference exists. -// This works with std::iterators. +// The default works with std::iterators. + template struct return_type_1, A> { - typedef typename A::reference type; + typedef typename std::iterator_traits::reference type; }; // strip reference @@ -188,10 +200,12 @@ struct return_type_1, const A> { >::RET type; }; +// not needed really (base case should take care of this as well) template struct return_type_1, A*> { typedef A& type; }; // the pointers itself can be const, this const may safely be dropped +// not needed really (base case should take care of this as well) template struct return_type_1, A* const> { typedef A& type; @@ -412,20 +426,39 @@ struct return_type_2, A, B> // plus_action is just a random pick, has to be a concrete instance }; -// TODO: templated streams -// ostream +// leftshift_action case takes care of stream references, +// and if A is not a stream, it delegates the work to this specialization +template +struct return_type_2, A, B> +{ + // the default is the type of the left argument (as non-reference type) + typedef + typename boost::remove_const< + typename boost::remove_reference::type + >::type type; +}; + +template +struct return_type_2, A, B> +{ + typedef + typename boost::remove_const< + typename boost::remove_reference::type + >::type type; +}; + +#ifdef BOOST_NO_TEMPLATED_STREAMS template struct return_type_2, A, B> { typedef typename detail::IF< - boost::is_convertible< - typename boost::remove_reference::type*, std::ostream*>::value, - typename boost::add_reference::type, //reference to the stream - typename boost::remove_reference::type - // for left shift, the default resulting type is the same as the left - // operand. A can however be a reference (if it comes from a free variable - // or if cref or ref wrappers have been used), - // so we return a plain type. + boost::is_convertible< + typename boost::remove_reference::type*, + std::ostream* + >::value, + A, //reference to the stream + typename + return_type_2, A, B>::type >::RET type; }; @@ -434,17 +467,48 @@ template struct return_type_2, A, B> { typedef typename detail::IF< - boost::is_convertible::type*, - std::istream*>::value, - typename boost::add_reference::type, // ref to the stream type - typename boost::remove_reference::type - // for right shift, the default resulting type is the same as the - // left operand. A can however be a reference (if it comes from a - //free variable or if cref or ref - // wrappers have been used), so we return a const plain type. + boost::is_convertible< + typename boost::remove_reference::type*, + std::istream* + >::value, + A, // the stream type (A should be ref) + typename + return_type_2, A, B>::type >::RET type; }; +#else +// ostream +template +struct return_type_2, A, B> +{ + typedef typename detail::IF< + is_instance_of_2< + typename boost::remove_reference::type, + std::basic_ostream + >::value, + A, //reference to the stream + typename + return_type_2, A, B>::type + >::RET type; +}; + +// istream +template +struct return_type_2, A, B> +{ + typedef typename detail::IF< + is_instance_of_2< + typename boost::remove_reference::type, + std::basic_istream + >::value, + A, // the stream type (A should be ref) + typename + return_type_2, A, B>::type + >::RET type; +}; +#endif + // -- logical actions ---------------------------------------- // always bool // NOTE: this may not be true for some weird user-defined types, @@ -509,14 +573,13 @@ struct return_type_2, const A, B> { }; -// TODO: this may fail directly, find a way around it - -// The general case, matches all plain class types -// this covers vectors and sets (or any other container that -// defines the typedef value_type +// The general case used to check if this a typedef value_type was defined +// That could fail so, it got changed and there are specializations +// for vector etc. template struct return_type_2, A, B> { - typedef typename A::value_type& type; + // typedef typename A::value_type& type; + typedef detail::unspecified type; }; @@ -546,18 +609,11 @@ struct return_type_2, A[N], B> { namespace std { template class map; template class multimap; + template class vector; + template class deque; + template class basic_string; } -// do the same as map for sgi's hash_map, and hash_multimap. -// The SGI STL Port is included because it is so commonly used. -#if defined __SGI_STL_PORT -namespace __STLPORT_NAMESPACE { -template class hash_map; -template class hash_multimap; -} -#endif namespace boost { namespace lambda { @@ -574,7 +630,51 @@ struct return_type_2, std::multimap::mapped_type; }; + // deque +template +struct return_type_2, std::deque, B> { + typedef typename std::deque::reference type; +}; +template +struct return_type_2, const std::deque, B> { + typedef typename std::deque::const_reference type; +}; + + // vector +template +struct return_type_2, std::vector, B> { + typedef typename std::vector::reference type; +}; +template +struct return_type_2, const std::vector, B> { + typedef typename std::vector::const_reference type; +}; + + // basic_string +template +struct return_type_2, std::basic_string, B> { + typedef typename std::basic_string::reference type; +}; +template +struct return_type_2, const std::basic_string, B> { + typedef typename std::basic_string::const_reference type; +}; + + + + #if defined __SGI_STL_PORT +// do the same as map for sgi's hash_map, and hash_multimap. +// The SGI STL Port is included because it is so commonly used. + +namespace __STLPORT_NAMESPACE { +template class hash_map; +template class hash_multimap; +} + + template struct return_type_2, ::__STLPORT_NAMESPACE::hash_map<_Key, _Tp, _HashFcn, _EqualKey, _Alloc>, B> { typedef _Tp& type;