[boost][range] - fix for ticket 6888 - unique predicate overloads

[SVN r85686]
This commit is contained in:
Neil Groves
2013-09-15 19:44:36 +00:00
committed by Nathan Ridge
parent fbc0057432
commit 3d3dea1411
7 changed files with 183 additions and 15 deletions

View File

@ -86,14 +86,14 @@ unique( const ForwardRange& rng )
/// \overload /// \overload
template< class ForwardRange, class BinaryPredicate > template< class ForwardRange, class BinaryPredicate >
inline BOOST_DEDUCED_TYPENAME range_return<ForwardRange, return_begin_found>::type inline BOOST_DEDUCED_TYPENAME range_return<ForwardRange, return_begin_found>::type
unique( ForwardRange& rng, BinaryPredicate ) unique( ForwardRange& rng, BinaryPredicate pred )
{ {
BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept<ForwardRange> )); BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept<ForwardRange> ));
return ::boost::range::unique<return_begin_found>(rng); return ::boost::range::unique<return_begin_found>(rng, pred);
} }
/// \overload /// \overload
template< class ForwardRange, class BinaryPredicate > template< class ForwardRange, class BinaryPredicate >
inline BOOST_DEDUCED_TYPENAME range_iterator<const ForwardRange>::type inline BOOST_DEDUCED_TYPENAME range_return<const ForwardRange, return_begin_found>::type
unique( const ForwardRange& rng, BinaryPredicate pred ) unique( const ForwardRange& rng, BinaryPredicate pred )
{ {
BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept<const ForwardRange> )); BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept<const ForwardRange> ));

6
include/boost/range/config.hpp Executable file → Normal file
View File

@ -48,6 +48,12 @@
#define BOOST_RANGE_ARRAY_REF() (&boost_range_array) #define BOOST_RANGE_ARRAY_REF() (&boost_range_array)
#endif #endif
#if defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)))
# define BOOST_RANGE_UNUSED __attribute__((unused))
#else
# define BOOST_RANGE_UNUSED
#endif
#endif #endif

View File

@ -13,6 +13,7 @@
// //
#include <boost/range/adaptor/strided.hpp> #include <boost/range/adaptor/strided.hpp>
#include <boost/config.hpp>
#include <boost/test/test_tools.hpp> #include <boost/test/test_tools.hpp>
#include <boost/test/unit_test.hpp> #include <boost/test/unit_test.hpp>
@ -42,9 +43,12 @@ namespace boost
Container reference; Container reference;
{ {
typedef BOOST_DEDUCED_TYPENAME Container::const_iterator iterator_t; typedef BOOST_DEDUCED_TYPENAME Container::const_iterator
typedef BOOST_DEDUCED_TYPENAME Container::difference_type diff_t; iterator_t BOOST_RANGE_UNUSED;
typedef BOOST_DEDUCED_TYPENAME Container::size_type size_type; typedef BOOST_DEDUCED_TYPENAME Container::difference_type
diff_t BOOST_RANGE_UNUSED;
typedef BOOST_DEDUCED_TYPENAME Container::size_type
size_type BOOST_RANGE_UNUSED;
iterator_t it = c.begin(); iterator_t it = c.begin();
iterator_t last = c.end(); iterator_t last = c.end();

View File

@ -35,6 +35,7 @@
#endif #endif
#include <boost/assign.hpp> #include <boost/assign.hpp>
#include <boost/config.hpp>
#include <boost/array.hpp> #include <boost/array.hpp>
#include <boost/bind.hpp> #include <boost/bind.hpp>
#include <boost/range/numeric.hpp> #include <boost/range/numeric.hpp>
@ -107,9 +108,11 @@ void test_random_algorithms(Rng & rng, std::random_access_iterator_tag)
{ {
typedef BOOST_DEDUCED_TYPENAME boost::range_iterator<Rng>::type iterator; typedef BOOST_DEDUCED_TYPENAME boost::range_iterator<Rng>::type iterator;
typedef BOOST_DEDUCED_TYPENAME boost::range_value<Rng>::type value_type; typedef BOOST_DEDUCED_TYPENAME boost::range_value<Rng>::type value_type;
typedef BOOST_DEDUCED_TYPENAME boost::range_size<Rng>::type size_type; typedef BOOST_DEDUCED_TYPENAME boost::range_size<Rng>::type size_type BOOST_RANGE_UNUSED;
typedef BOOST_DEDUCED_TYPENAME boost::iterator_category<iterator>::type iterator_category; typedef BOOST_DEDUCED_TYPENAME boost::iterator_category<iterator>::type iterator_category;
// just make sure these compile (for now) // just make sure these compile (for now)
if(0) if(0)
{ {
@ -328,6 +331,8 @@ void test_algorithms(Rng & rng)
o = boost::adjacent_difference( rng, boost::begin(out) ); o = boost::adjacent_difference( rng, boost::begin(out) );
o = boost::adjacent_difference( rng, boost::begin(out), o = boost::adjacent_difference( rng, boost::begin(out),
null_op2() ); null_op2() );
boost::ignore_unused_variable_warning(b);
} }

View File

@ -9,13 +9,15 @@
// For more information, see http://www.boost.org/libs/range/ // For more information, see http://www.boost.org/libs/range/
// //
#include <boost/range/algorithm/unique.hpp> #include <boost/range/algorithm/unique.hpp>
#include <boost/range/detail/range_return.hpp>
#include <boost/test/test_tools.hpp> #include <boost/test/test_tools.hpp>
#include <boost/test/unit_test.hpp> #include <boost/test/unit_test.hpp>
#include <boost/assign.hpp> #include <boost/assign.hpp>
#include <boost/bind.hpp> #include <boost/bind.hpp>
#include "../test_driver/range_return_test_driver.hpp" #include <boost/config.hpp>
#include "../test_driver/range_overload_test_driver.hpp"
#include <algorithm> #include <algorithm>
#include <functional> #include <functional>
#include <list> #include <list>
@ -60,6 +62,36 @@ namespace boost_range_test_algorithm_unique
} }
}; };
template<typename Container>
struct test_range_overload
{
BOOST_STATIC_CONSTANT(
::boost::range_return_value,
result_type = ::boost::return_begin_found);
template<typename Policy>
BOOST_DEDUCED_TYPENAME boost::range_return<
Container, result_type
>::type
operator()(Policy& policy, Container& cont)
{
typedef BOOST_DEDUCED_TYPENAME boost::range_return<
Container,result_type>::type result_t;
Container cont2(cont);
result_t result = boost::unique(cont);
boost::unique(boost::make_iterator_range(cont2));
BOOST_CHECK_EQUAL_COLLECTIONS(
cont.begin(), cont.end(),
cont2.begin(), cont2.end());
return result;
}
};
template< class Container > template< class Container >
BOOST_DEDUCED_TYPENAME boost::range_iterator<Container>::type BOOST_DEDUCED_TYPENAME boost::range_iterator<Container>::type
reference(Container& cont) reference(Container& cont)
@ -67,7 +99,7 @@ namespace boost_range_test_algorithm_unique
return std::unique(cont.begin(), cont.end()); return std::unique(cont.begin(), cont.end());
} }
}; };
// test the 'unique' algorithm with a predicate // test the 'unique' algorithm with a predicate
template<class Pred> template<class Pred>
class unique_pred_test_policy class unique_pred_test_policy
@ -105,6 +137,34 @@ namespace boost_range_test_algorithm_unique
return result; return result;
} }
}; };
template<typename Container>
struct test_range_overload
{
BOOST_STATIC_CONSTANT(
::boost::range_return_value,
result_type = ::boost::return_begin_found);
template<typename Policy>
BOOST_DEDUCED_TYPENAME boost::range_return<Container,result_type>::type
operator()(Policy& policy, Container& cont)
{
typedef BOOST_DEDUCED_TYPENAME boost::range_return<
Container,result_type>::type result_t;
Container cont2(cont);
result_t result = boost::unique(cont, policy.pred());
boost::unique(boost::make_iterator_range(cont2), policy.pred());
BOOST_CHECK_EQUAL_COLLECTIONS(
cont.begin(), cont.end(),
cont2.begin(), cont2.end());
return result;
}
};
template< class Container > template< class Container >
BOOST_DEDUCED_TYPENAME boost::range_iterator<Container>::type BOOST_DEDUCED_TYPENAME boost::range_iterator<Container>::type
@ -121,7 +181,7 @@ namespace boost_range_test_algorithm_unique
typedef BOOST_DEDUCED_TYPENAME Container::value_type value_t; typedef BOOST_DEDUCED_TYPENAME Container::value_type value_t;
boost::range_test::range_return_test_driver test_driver; boost::range_test::range_overload_test_driver test_driver;
Container cont; Container cont;
@ -145,6 +205,19 @@ namespace boost_range_test_algorithm_unique
test_driver(cont, policy); test_driver(cont, policy);
} }
template<typename T>
struct equal_div_2
{
typedef bool result_type;
typedef const T& first_argument_type;
typedef const T& second_argument_type;
bool operator()(const T& left, const T& right) const
{
return left / 2 == right / 2;
}
};
template<class Container> template<class Container>
void test_unique_impl() void test_unique_impl()
@ -152,17 +225,22 @@ namespace boost_range_test_algorithm_unique
test_unique_impl<Container>( test_unique_impl<Container>(
unique_test_policy(), unique_test_policy(),
std::less<int>() std::less<int>()
); );
test_unique_impl<Container>( test_unique_impl<Container>(
unique_pred_test_policy<std::less<int> >(), unique_pred_test_policy<std::equal_to<int> >(),
std::less<int>() std::less<int>()
); );
test_unique_impl<Container>( test_unique_impl<Container>(
unique_pred_test_policy<std::greater<int> >(), unique_pred_test_policy<std::equal_to<int> >(),
std::greater<int>() std::greater<int>()
); );
test_unique_impl<Container>(
unique_pred_test_policy<equal_div_2<int> >(),
std::less<int>()
);
} }
void test_unique() void test_unique()

View File

@ -16,6 +16,7 @@ namespace iterator_range_test_detail
{ {
double source[] = { 0.0, 1.0, 2.0, 3.0, 4.0, 5.0 }; double source[] = { 0.0, 1.0, 2.0, 3.0, 4.0, 5.0 };
boost::iterator_range<float*> rng = boost::make_iterator_range(source); boost::iterator_range<float*> rng = boost::make_iterator_range(source);
boost::ignore_unused_variable_warning(rng);
} }
} }

View File

@ -0,0 +1,74 @@
// Copyright Neil Groves 2013. 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/
//
// Acknowledgments:
// Implemented by Andy in response to Ticket 6888 - unique fix
//
#ifndef BOOST_RANGE_TEST_TEST_DRIVER_RANGE_OVERLOAD_TEST_DRIVER_HPP_INCLUDED
#define BOOST_RANGE_TEST_TEST_DRIVER_RANGE_OVERLOAD_TEST_DRIVER_HPP_INCLUDED
#include "range_return_test_driver.hpp"
#include <boost/assert.hpp>
#include <boost/test/test_tools.hpp>
#include <boost/test/unit_test.hpp>
namespace boost
{
namespace range_test
{
// A test driver to exercise a test through range_return_test_driver
// plus the overload that determines the return_type by overload
//
// The test driver also contains the code required to check the
// return value correctness.
//
// The TestPolicy needs to implement all those required by
// range_return_test_driver, and additionally
//
// - perform the boost range version of the algorithm that determines
// the return_type by overload
class range_overload_test_driver : range_return_test_driver
{
public:
template< class Container,
class TestPolicy >
void operator()(Container& cont, TestPolicy policy)
{
range_return_test_driver::operator()(cont, policy);
test_range_overload<Container, TestPolicy>()(cont, policy);
}
private:
template< class Container, class TestPolicy >
struct test_range_overload
{
void operator()(Container& cont, TestPolicy policy)
{
typedef BOOST_DEDUCED_TYPENAME range_iterator<Container>::type iterator_t;
typedef BOOST_DEDUCED_TYPENAME TestPolicy::template test_range_overload<Container> test_range_overload_t;
const range_return_value result_type = test_range_overload_t::result_type;
typedef BOOST_DEDUCED_TYPENAME range_return<Container, result_type>::type range_return_t;
Container reference(cont);
Container test_cont(cont);
test_range_overload_t test_range_overload_fn;
range_return_t range_result = test_range_overload_fn(policy, test_cont);
iterator_t reference_it = policy.reference(reference);
check_results<result_type>::test(test_cont, reference,
range_result, reference_it);
}
};
};
}
}
#endif // include guard