forked from boostorg/range
attempted fix for iterator_range relational operators bug
This commit is contained in:
@ -26,9 +26,11 @@
|
|||||||
#include <boost/iterator/iterator_traits.hpp>
|
#include <boost/iterator/iterator_traits.hpp>
|
||||||
#include <boost/iterator/iterator_facade.hpp>
|
#include <boost/iterator/iterator_facade.hpp>
|
||||||
#include <boost/mpl/if.hpp>
|
#include <boost/mpl/if.hpp>
|
||||||
|
#include <boost/mpl/not.hpp>
|
||||||
#include <boost/mpl/or.hpp>
|
#include <boost/mpl/or.hpp>
|
||||||
#include <boost/type_traits/is_abstract.hpp>
|
#include <boost/type_traits/is_abstract.hpp>
|
||||||
#include <boost/type_traits/is_array.hpp>
|
#include <boost/type_traits/is_array.hpp>
|
||||||
|
#include <boost/type_traits/is_base_and_derived.hpp>
|
||||||
#include <boost/type_traits/is_convertible.hpp>
|
#include <boost/type_traits/is_convertible.hpp>
|
||||||
#include <boost/type_traits/is_function.hpp>
|
#include <boost/type_traits/is_function.hpp>
|
||||||
#include <boost/type_traits/is_pointer.hpp>
|
#include <boost/type_traits/is_pointer.hpp>
|
||||||
@ -539,143 +541,174 @@ public:
|
|||||||
/////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////
|
||||||
// comparison operators
|
// comparison operators
|
||||||
/////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////
|
||||||
template<class SinglePassRange1, class SinglePassRange2>
|
|
||||||
inline BOOST_DEDUCED_TYPENAME ::boost::enable_if<
|
template< class IteratorT, class ForwardRange >
|
||||||
mpl::or_<
|
inline BOOST_DEDUCED_TYPENAME boost::enable_if<
|
||||||
is_convertible<
|
mpl::not_<is_base_and_derived<iterator_range_detail::iterator_range_tag, ForwardRange> >,
|
||||||
const SinglePassRange1&,
|
|
||||||
const iterator_range_detail::iterator_range_tag&
|
|
||||||
>,
|
|
||||||
is_convertible<
|
|
||||||
const SinglePassRange2&,
|
|
||||||
const iterator_range_detail::iterator_range_tag&
|
|
||||||
>
|
|
||||||
>,
|
|
||||||
bool
|
bool
|
||||||
>::type
|
>::type
|
||||||
operator==(const SinglePassRange1& l, const SinglePassRange2& r)
|
operator==( const ForwardRange& l, const iterator_range<IteratorT>& r )
|
||||||
{
|
{
|
||||||
BOOST_RANGE_CONCEPT_ASSERT((
|
return boost::equal( l, r );
|
||||||
boost::SinglePassRangeConcept<const SinglePassRange1>));
|
|
||||||
BOOST_RANGE_CONCEPT_ASSERT((
|
|
||||||
boost::SinglePassRangeConcept<const SinglePassRange2>));
|
|
||||||
return boost::equal(l, r);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class SinglePassRange1, class SinglePassRange2>
|
|
||||||
inline BOOST_DEDUCED_TYPENAME ::boost::enable_if<
|
|
||||||
mpl::or_<
|
|
||||||
is_convertible<
|
|
||||||
const SinglePassRange1&,
|
|
||||||
const iterator_range_detail::iterator_range_tag&
|
|
||||||
>,
|
|
||||||
is_convertible<
|
|
||||||
const SinglePassRange2&,
|
|
||||||
const iterator_range_detail::iterator_range_tag&
|
|
||||||
>
|
|
||||||
>,
|
|
||||||
bool
|
|
||||||
>::type
|
|
||||||
operator!=(const SinglePassRange1& l, const SinglePassRange2& r)
|
|
||||||
{
|
|
||||||
BOOST_RANGE_CONCEPT_ASSERT((
|
|
||||||
boost::SinglePassRangeConcept<const SinglePassRange1>));
|
|
||||||
BOOST_RANGE_CONCEPT_ASSERT((
|
|
||||||
boost::SinglePassRangeConcept<const SinglePassRange2>));
|
|
||||||
return !boost::equal(l, r);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class SinglePassRange1, class SinglePassRange2>
|
template< class IteratorT, class ForwardRange >
|
||||||
inline BOOST_DEDUCED_TYPENAME ::boost::enable_if<
|
inline BOOST_DEDUCED_TYPENAME boost::enable_if<
|
||||||
mpl::or_<
|
mpl::not_<boost::is_base_and_derived<iterator_range_detail::iterator_range_tag, ForwardRange> >,
|
||||||
is_convertible<
|
|
||||||
const SinglePassRange1&,
|
|
||||||
const iterator_range_detail::iterator_range_tag&
|
|
||||||
>,
|
|
||||||
is_convertible<
|
|
||||||
const SinglePassRange2&,
|
|
||||||
const iterator_range_detail::iterator_range_tag&
|
|
||||||
>
|
|
||||||
>,
|
|
||||||
bool
|
bool
|
||||||
>::type
|
>::type
|
||||||
operator<(const SinglePassRange1& l, const SinglePassRange2& r)
|
operator!=( const ForwardRange& l, const iterator_range<IteratorT>& r )
|
||||||
{
|
{
|
||||||
BOOST_RANGE_CONCEPT_ASSERT((
|
return !boost::equal( l, r );
|
||||||
boost::SinglePassRangeConcept<const SinglePassRange1>));
|
|
||||||
BOOST_RANGE_CONCEPT_ASSERT((
|
|
||||||
boost::SinglePassRangeConcept<const SinglePassRange2>));
|
|
||||||
return iterator_range_detail::less_than(l, r);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class SinglePassRange1, class SinglePassRange2>
|
template< class IteratorT, class ForwardRange >
|
||||||
inline BOOST_DEDUCED_TYPENAME ::boost::enable_if<
|
inline BOOST_DEDUCED_TYPENAME boost::enable_if<
|
||||||
mpl::or_<
|
mpl::not_<boost::is_base_and_derived<iterator_range_detail::iterator_range_tag, ForwardRange> >,
|
||||||
is_convertible<
|
|
||||||
const SinglePassRange1&,
|
|
||||||
const iterator_range_detail::iterator_range_tag&
|
|
||||||
>,
|
|
||||||
is_convertible<
|
|
||||||
const SinglePassRange2&,
|
|
||||||
const iterator_range_detail::iterator_range_tag&
|
|
||||||
>
|
|
||||||
>,
|
|
||||||
bool
|
bool
|
||||||
>::type
|
>::type
|
||||||
operator<=(const SinglePassRange1& l, const SinglePassRange2& r)
|
operator<( const ForwardRange& l, const iterator_range<IteratorT>& r )
|
||||||
{
|
{
|
||||||
BOOST_RANGE_CONCEPT_ASSERT((
|
return iterator_range_detail::less_than( l, r );
|
||||||
boost::SinglePassRangeConcept<const SinglePassRange1>));
|
|
||||||
BOOST_RANGE_CONCEPT_ASSERT((
|
|
||||||
boost::SinglePassRangeConcept<const SinglePassRange2>));
|
|
||||||
return iterator_range_detail::less_or_equal_than(l, r);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class SinglePassRange1, class SinglePassRange2>
|
template< class IteratorT, class ForwardRange >
|
||||||
inline BOOST_DEDUCED_TYPENAME ::boost::enable_if<
|
inline BOOST_DEDUCED_TYPENAME boost::enable_if<
|
||||||
mpl::or_<
|
mpl::not_<boost::is_base_and_derived<iterator_range_detail::iterator_range_tag, ForwardRange> >,
|
||||||
is_convertible<
|
|
||||||
const SinglePassRange1&,
|
|
||||||
const iterator_range_detail::iterator_range_tag&
|
|
||||||
>,
|
|
||||||
is_convertible<
|
|
||||||
const SinglePassRange2&,
|
|
||||||
const iterator_range_detail::iterator_range_tag&
|
|
||||||
>
|
|
||||||
>,
|
|
||||||
bool
|
bool
|
||||||
>::type
|
>::type
|
||||||
operator>(const SinglePassRange1& l, const SinglePassRange2& r)
|
operator<=( const ForwardRange& l, const iterator_range<IteratorT>& r )
|
||||||
{
|
{
|
||||||
BOOST_RANGE_CONCEPT_ASSERT((
|
return iterator_range_detail::less_or_equal_than( l, r );
|
||||||
boost::SinglePassRangeConcept<const SinglePassRange1>));
|
|
||||||
BOOST_RANGE_CONCEPT_ASSERT((
|
|
||||||
boost::SinglePassRangeConcept<const SinglePassRange2>));
|
|
||||||
return iterator_range_detail::greater_than(l, r);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class SinglePassRange1, class SinglePassRange2>
|
template< class IteratorT, class ForwardRange >
|
||||||
inline BOOST_DEDUCED_TYPENAME ::boost::enable_if<
|
inline BOOST_DEDUCED_TYPENAME boost::enable_if<
|
||||||
mpl::or_<
|
mpl::not_<boost::is_base_and_derived<iterator_range_detail::iterator_range_tag, ForwardRange> >,
|
||||||
is_convertible<
|
|
||||||
const SinglePassRange1&,
|
|
||||||
const iterator_range_detail::iterator_range_tag&
|
|
||||||
>,
|
|
||||||
is_convertible<
|
|
||||||
const SinglePassRange2&,
|
|
||||||
const iterator_range_detail::iterator_range_tag&
|
|
||||||
>
|
|
||||||
>,
|
|
||||||
bool
|
bool
|
||||||
>::type
|
>::type
|
||||||
operator>=(const SinglePassRange1& l, const SinglePassRange2& r)
|
operator>( const ForwardRange& l, const iterator_range<IteratorT>& r )
|
||||||
{
|
{
|
||||||
BOOST_RANGE_CONCEPT_ASSERT((
|
return iterator_range_detail::greater_than( l, r );
|
||||||
boost::SinglePassRangeConcept<const SinglePassRange1>));
|
|
||||||
BOOST_RANGE_CONCEPT_ASSERT((
|
|
||||||
boost::SinglePassRangeConcept<const SinglePassRange2>));
|
|
||||||
return iterator_range_detail::greater_or_equal_than(l, r);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template< class IteratorT, class ForwardRange >
|
||||||
|
inline BOOST_DEDUCED_TYPENAME boost::enable_if<
|
||||||
|
mpl::not_<boost::is_base_and_derived<iterator_range_detail::iterator_range_tag, ForwardRange> >,
|
||||||
|
bool
|
||||||
|
>::type
|
||||||
|
operator>=( const ForwardRange& l, const iterator_range<IteratorT>& r )
|
||||||
|
{
|
||||||
|
return iterator_range_detail::greater_or_equal_than( l, r );
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
|
||||||
|
#else
|
||||||
|
template< class Iterator1T, class Iterator2T >
|
||||||
|
inline bool
|
||||||
|
operator==( const iterator_range<Iterator1T>& l, const iterator_range<Iterator2T>& r )
|
||||||
|
{
|
||||||
|
return boost::equal( l, r );
|
||||||
|
}
|
||||||
|
|
||||||
|
template< class IteratorT, class ForwardRange >
|
||||||
|
inline BOOST_DEDUCED_TYPENAME boost::enable_if<
|
||||||
|
mpl::not_<boost::is_base_and_derived<iterator_range_detail::iterator_range_tag, ForwardRange> >,
|
||||||
|
bool
|
||||||
|
>::type
|
||||||
|
operator==( const iterator_range<IteratorT>& l, const ForwardRange& r )
|
||||||
|
{
|
||||||
|
return boost::equal( l, r );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template< class Iterator1T, class Iterator2T >
|
||||||
|
inline bool
|
||||||
|
operator!=( const iterator_range<Iterator1T>& l, const iterator_range<Iterator2T>& r )
|
||||||
|
{
|
||||||
|
return !boost::equal( l, r );
|
||||||
|
}
|
||||||
|
|
||||||
|
template< class IteratorT, class ForwardRange >
|
||||||
|
inline BOOST_DEDUCED_TYPENAME boost::enable_if<
|
||||||
|
mpl::not_<boost::is_base_and_derived<iterator_range_detail::iterator_range_tag, ForwardRange> >,
|
||||||
|
bool
|
||||||
|
>::type
|
||||||
|
operator!=( const iterator_range<IteratorT>& l, const ForwardRange& r )
|
||||||
|
{
|
||||||
|
return !boost::equal( l, r );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template< class Iterator1T, class Iterator2T >
|
||||||
|
inline bool
|
||||||
|
operator<( const iterator_range<Iterator1T>& l, const iterator_range<Iterator2T>& r )
|
||||||
|
{
|
||||||
|
return iterator_range_detail::less_than( l, r );
|
||||||
|
}
|
||||||
|
|
||||||
|
template< class IteratorT, class ForwardRange >
|
||||||
|
inline BOOST_DEDUCED_TYPENAME boost::enable_if<
|
||||||
|
mpl::not_<boost::is_base_and_derived<iterator_range_detail::iterator_range_tag, ForwardRange> >,
|
||||||
|
bool
|
||||||
|
>::type
|
||||||
|
operator<( const iterator_range<IteratorT>& l, const ForwardRange& r )
|
||||||
|
{
|
||||||
|
return iterator_range_detail::less_than( l, r );
|
||||||
|
}
|
||||||
|
|
||||||
|
template< class Iterator1T, class Iterator2T >
|
||||||
|
inline bool
|
||||||
|
operator<=( const iterator_range<Iterator1T>& l, const iterator_range<Iterator2T>& r )
|
||||||
|
{
|
||||||
|
return iterator_range_detail::less_or_equal_than( l, r );
|
||||||
|
}
|
||||||
|
|
||||||
|
template< class IteratorT, class ForwardRange >
|
||||||
|
inline BOOST_DEDUCED_TYPENAME boost::enable_if<
|
||||||
|
mpl::not_<boost::is_base_and_derived<iterator_range_detail::iterator_range_tag, ForwardRange> >,
|
||||||
|
bool
|
||||||
|
>::type
|
||||||
|
operator<=( const iterator_range<IteratorT>& l, const ForwardRange& r )
|
||||||
|
{
|
||||||
|
return iterator_range_detail::less_or_equal_than( l, r );
|
||||||
|
}
|
||||||
|
|
||||||
|
template< class Iterator1T, class Iterator2T >
|
||||||
|
inline bool
|
||||||
|
operator>( const iterator_range<Iterator1T>& l, const iterator_range<Iterator2T>& r )
|
||||||
|
{
|
||||||
|
return iterator_range_detail::greater_than( l, r );
|
||||||
|
}
|
||||||
|
|
||||||
|
template< class IteratorT, class ForwardRange >
|
||||||
|
inline BOOST_DEDUCED_TYPENAME boost::enable_if<
|
||||||
|
mpl::not_<boost::is_base_and_derived<iterator_range_detail::iterator_range_tag, ForwardRange> >,
|
||||||
|
bool
|
||||||
|
>::type
|
||||||
|
operator>( const iterator_range<IteratorT>& l, const ForwardRange& r )
|
||||||
|
{
|
||||||
|
return iterator_range_detail::greater_than( l, r );
|
||||||
|
}
|
||||||
|
|
||||||
|
template< class Iterator1T, class Iterator2T >
|
||||||
|
inline bool
|
||||||
|
operator>=( const iterator_range<Iterator1T>& l, const iterator_range<Iterator2T>& r )
|
||||||
|
{
|
||||||
|
return iterator_range_detail::greater_or_equal_than( l, r );
|
||||||
|
}
|
||||||
|
|
||||||
|
template< class IteratorT, class ForwardRange >
|
||||||
|
inline BOOST_DEDUCED_TYPENAME boost::enable_if<
|
||||||
|
mpl::not_<boost::is_base_and_derived<iterator_range_detail::iterator_range_tag, ForwardRange> >,
|
||||||
|
bool
|
||||||
|
>::type
|
||||||
|
operator>=( const iterator_range<IteratorT>& l, const ForwardRange& r )
|
||||||
|
{
|
||||||
|
return iterator_range_detail::greater_or_equal_than( l, r );
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // BOOST_NO_FUNCTION_TEMPLATE_ORDERING
|
||||||
|
|
||||||
// iterator range utilities -----------------------------------------//
|
// iterator range utilities -----------------------------------------//
|
||||||
|
|
||||||
|
@ -194,6 +194,7 @@ test-suite range :
|
|||||||
[ range-test iterator_pair ]
|
[ range-test iterator_pair ]
|
||||||
[ range-test iterator_range ]
|
[ range-test iterator_range ]
|
||||||
[ range-test iterator_range_drop ]
|
[ range-test iterator_range_drop ]
|
||||||
|
[ range-test iterator_range_equality_bug ]
|
||||||
[ range-test iterator_range_hash ]
|
[ range-test iterator_range_hash ]
|
||||||
[ range-test iterator_range_variant ]
|
[ range-test iterator_range_variant ]
|
||||||
# [ range-test mfc : <include>$(VC71_ROOT)/atlmfc/include ]
|
# [ range-test mfc : <include>$(VC71_ROOT)/atlmfc/include ]
|
||||||
|
39
test/iterator_range_equality_bug.cpp
Normal file
39
test/iterator_range_equality_bug.cpp
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
// Boost.Range library
|
||||||
|
//
|
||||||
|
// Copyright Neil Groves 2014. Use, modification and
|
||||||
|
// distribution is subject to 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 http://www.boost.org/libs/range/
|
||||||
|
//
|
||||||
|
// As reported in https://groups.google.com/forum/#!msg/boost-developers-archive/6JVNg7ZPb4k/RAlvPUec4MAJ
|
||||||
|
|
||||||
|
#include <boost/range/iterator_range_core.hpp>
|
||||||
|
#include <boost/lambda/lambda.hpp>
|
||||||
|
#include <boost/algorithm/string.hpp>
|
||||||
|
|
||||||
|
namespace boost
|
||||||
|
{
|
||||||
|
enum {unnamed};
|
||||||
|
struct S {
|
||||||
|
bool operator<(int) const {return false;}
|
||||||
|
bool operator==(int) const {return false;}
|
||||||
|
};
|
||||||
|
template<typename T>
|
||||||
|
bool foo(T i)
|
||||||
|
{
|
||||||
|
return i < unnamed || i == unnamed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
using boost::lambda::_1;
|
||||||
|
(void)(_1 == 42);
|
||||||
|
(void)(42 == _1);
|
||||||
|
|
||||||
|
boost::foo(42);
|
||||||
|
boost::foo(boost::S());
|
||||||
|
}
|
Reference in New Issue
Block a user