mirror of
https://github.com/boostorg/range.git
synced 2025-07-28 11:57:38 +02:00
[boost][range] - Improved handling of temporary ranges in range algorithms.
[SVN r63904]
This commit is contained in:
@ -15,19 +15,129 @@
|
|||||||
|
|
||||||
#include <boost/assign.hpp>
|
#include <boost/assign.hpp>
|
||||||
#include <boost/range/algorithm_ext.hpp>
|
#include <boost/range/algorithm_ext.hpp>
|
||||||
|
#include <boost/range/sub_range.hpp>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
namespace boost
|
namespace boost
|
||||||
{
|
{
|
||||||
|
namespace range3
|
||||||
|
{
|
||||||
|
namespace concept
|
||||||
|
{
|
||||||
|
template<class Range>
|
||||||
|
class PopFrontSubRange
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void constraints()
|
||||||
|
{
|
||||||
|
Range copied_range(*m_range);
|
||||||
|
BOOST_DEDUCED_TYPENAME range_value<Range>::type v = copied_range.front();
|
||||||
|
copied_range.pop_front();
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
Range* m_range;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class Range>
|
||||||
|
class PopBackSubRange
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void constraints()
|
||||||
|
{
|
||||||
|
Range copied_range(*m_range);
|
||||||
|
BOOST_DEDUCED_TYPENAME range_value<Range>::type v = copied_range.back();
|
||||||
|
copied_range.pop_back();
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
Range* m_range;
|
||||||
|
};
|
||||||
|
} // namespace concept
|
||||||
|
namespace adaptor
|
||||||
|
{
|
||||||
|
template<class Range, class Pred>
|
||||||
|
class adjacent_filter_adaptor
|
||||||
|
: private boost::sub_range<Range>
|
||||||
|
, private Pred
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef boost::sub_range<Range> range_t;
|
||||||
|
typedef Pred pred_t;
|
||||||
|
typedef typename range_t::value_type value_type;
|
||||||
|
using range_t::reference;
|
||||||
|
using range_t::const_reference;
|
||||||
|
using range_t::empty;
|
||||||
|
using range_t::front;
|
||||||
|
using range_t::back;
|
||||||
|
|
||||||
|
adjacent_filter_adaptor(Range& rng, Pred pred)
|
||||||
|
: range_t(rng)
|
||||||
|
, pred_t(pred)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void pop_front()
|
||||||
|
{
|
||||||
|
BOOST_ASSERT( !empty() );
|
||||||
|
const value_type& old_front = front();
|
||||||
|
range_t::pop_front();
|
||||||
|
while (!empty() && !pred_t::operator()(front(), old_front))
|
||||||
|
range_t::pop_front();
|
||||||
|
}
|
||||||
|
|
||||||
|
void pop_back()
|
||||||
|
{
|
||||||
|
BOOST_ASSERT( !empty() );
|
||||||
|
const value_type& old_back = back();
|
||||||
|
range_t::pop_back();
|
||||||
|
while (!empty() && !pred_t::operator()(old_back, back()))
|
||||||
|
range_t::pop_back();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class Range>
|
||||||
|
class unique_adaptor
|
||||||
|
: public adjacent_filter_adaptor<Range, std::not_equal_to< typename range_value<Range>::type > >
|
||||||
|
{
|
||||||
|
typedef adjacent_filter_adaptor<Range, std::not_equal_to< typename range_value<Range>::type > > base_t;
|
||||||
|
public:
|
||||||
|
typedef std::not_equal_to< typename range_value<Range>::type > pred_t;
|
||||||
|
explicit unique_adaptor(Range& rng) : base_t(rng, pred_t()) {}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
template< class Container >
|
||||||
|
void new_uniqued_adaptor_test(Container& c)
|
||||||
|
{
|
||||||
|
std::vector<int> test_result1;
|
||||||
|
boost::range3::adaptor::unique_adaptor<Container> rng(c);
|
||||||
|
while (!rng.empty())
|
||||||
|
{
|
||||||
|
test_result1.push_back(rng.front());
|
||||||
|
rng.pop_front();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<int> test_result2;
|
||||||
|
boost::push_back(test_result2, adaptors::unique(c));
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL_COLLECTIONS(
|
||||||
|
test_result1.begin(), test_result1.end(),
|
||||||
|
test_result2.begin(), test_result2.end()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
template< class Container >
|
template< class Container >
|
||||||
void uniqued_test_impl( Container& c )
|
void uniqued_test_impl( Container& c )
|
||||||
{
|
{
|
||||||
|
new_uniqued_adaptor_test(c);
|
||||||
|
|
||||||
using namespace boost::adaptors;
|
using namespace boost::adaptors;
|
||||||
|
|
||||||
std::vector< int > test_result1;
|
std::vector< int > test_result1;
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
# pragma warn -8057 // unused argument argc/argv in Boost.Test
|
# pragma warn -8057 // unused argument argc/argv in Boost.Test
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <boost/array.hpp>
|
||||||
#include <boost/range/as_array.hpp>
|
#include <boost/range/as_array.hpp>
|
||||||
#include <boost/range/as_literal.hpp>
|
#include <boost/range/as_literal.hpp>
|
||||||
#include <boost/range/functions.hpp>
|
#include <boost/range/functions.hpp>
|
||||||
@ -29,6 +30,34 @@
|
|||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
template< class CharT, std::size_t Length >
|
||||||
|
class test_string
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef CharT value_type;
|
||||||
|
typedef value_type* pointer;
|
||||||
|
typedef const value_type* const_pointer;
|
||||||
|
typedef std::size_t size_type;
|
||||||
|
typedef value_type array_t[Length];
|
||||||
|
typedef const value_type const_array_t[Length];
|
||||||
|
|
||||||
|
explicit test_string(const CharT literal_sz[])
|
||||||
|
{
|
||||||
|
std::copy(literal_sz, literal_sz + Length, m_buffer.data());
|
||||||
|
m_buffer[Length] = value_type();
|
||||||
|
}
|
||||||
|
|
||||||
|
const_pointer const_sz() const { return m_buffer.data(); }
|
||||||
|
pointer mutable_sz() { return m_buffer.data(); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
typedef boost::array<value_type, Length + 1> buffer_t;
|
||||||
|
buffer_t m_buffer;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
template< class T >
|
template< class T >
|
||||||
inline BOOST_DEDUCED_TYPENAME boost::range_iterator<T>::type
|
inline BOOST_DEDUCED_TYPENAME boost::range_iterator<T>::type
|
||||||
str_begin( T& r )
|
str_begin( T& r )
|
||||||
@ -105,11 +134,15 @@ void check_char()
|
|||||||
{
|
{
|
||||||
typedef char* char_iterator_t;
|
typedef char* char_iterator_t;
|
||||||
typedef char char_array_t[10];
|
typedef char char_array_t[10];
|
||||||
const char* char_s = "a string";
|
|
||||||
char my_string[] = "another string";
|
test_string<char, 8> a_string("a string");
|
||||||
|
test_string<char, 14> another_string("another string");
|
||||||
|
|
||||||
|
const char* char_s = a_string.const_sz();
|
||||||
|
char my_string[] = "another_string";
|
||||||
const char my_const_string[] = "another string";
|
const char my_const_string[] = "another string";
|
||||||
const unsigned my_string_length = 14;
|
const unsigned my_string_length = 14;
|
||||||
char* char_s2 = "a string";
|
char* char_s2 = a_string.mutable_sz();
|
||||||
|
|
||||||
BOOST_STATIC_ASSERT(( is_same< range_value<char_iterator_t>::type,
|
BOOST_STATIC_ASSERT(( is_same< range_value<char_iterator_t>::type,
|
||||||
detail::iterator_traits<char_iterator_t>::value_type>::value ));
|
detail::iterator_traits<char_iterator_t>::value_type>::value ));
|
||||||
@ -181,10 +214,14 @@ void check_string()
|
|||||||
check_char();
|
check_char();
|
||||||
|
|
||||||
#ifndef BOOST_NO_STD_WSTRING
|
#ifndef BOOST_NO_STD_WSTRING
|
||||||
typedef wchar_t* wchar_iterator_t;
|
typedef wchar_t* wchar_iterator_t;
|
||||||
const wchar_t* char_ws = L"a wide string";
|
|
||||||
|
test_string<wchar_t, 13> a_wide_string(L"a wide string");
|
||||||
|
test_string<wchar_t, 19> another_wide_string(L"another wide string");
|
||||||
|
|
||||||
|
const wchar_t* char_ws = a_wide_string.const_sz();
|
||||||
wchar_t my_wstring[] = L"another wide string";
|
wchar_t my_wstring[] = L"another wide string";
|
||||||
wchar_t* char_ws2 = L"a wide string";
|
wchar_t* char_ws2 = a_wide_string.mutable_sz();
|
||||||
|
|
||||||
BOOST_STATIC_ASSERT(( is_same< range_value<wchar_iterator_t>::type,
|
BOOST_STATIC_ASSERT(( is_same< range_value<wchar_iterator_t>::type,
|
||||||
detail::iterator_traits<wchar_iterator_t>::value_type>::value ));
|
detail::iterator_traits<wchar_iterator_t>::value_type>::value ));
|
||||||
@ -203,12 +240,17 @@ void check_string()
|
|||||||
BOOST_CHECK_EQUAL( sz, std::char_traits<wchar_t>::length( char_ws ) );
|
BOOST_CHECK_EQUAL( sz, std::char_traits<wchar_t>::length( char_ws ) );
|
||||||
|
|
||||||
wchar_t to_search = L'n';
|
wchar_t to_search = L'n';
|
||||||
BOOST_CHECK( find( char_ws, to_search ) != str_end(char_ws) );
|
BOOST_CHECK( find( char_ws, to_search ) != str_end(char_ws) );
|
||||||
|
BOOST_CHECK( find( char_ws2, to_search ) != str_end(char_ws2) );
|
||||||
|
|
||||||
#if BOOST_WORKAROUND(_MSC_VER, BOOST_TESTED_AT(1300))
|
#if BOOST_WORKAROUND(_MSC_VER, BOOST_TESTED_AT(1300))
|
||||||
|
|
||||||
BOOST_CHECK( find( my_wstring, to_search ) != str_end(my_wstring) );
|
BOOST_CHECK( find( my_wstring, to_search ) != str_end(my_wstring) );
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
boost::ignore_unused_variable_warning( my_wstring );
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
29
test/test_function/true_predicate.hpp
Normal file
29
test/test_function/true_predicate.hpp
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
// Boost.Range library
|
||||||
|
//
|
||||||
|
// Copyright Neil Groves 2010. 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/
|
||||||
|
//
|
||||||
|
#ifndef BOOST_RANGE_TEST_TEST_FUNCTION_TRUE_PREDICATE_HPP_INCLUDED
|
||||||
|
#define BOOST_RANGE_TEST_TEST_FUNCTION_TRUE_PREDICATE_HPP_INCLUDED
|
||||||
|
|
||||||
|
namespace boost
|
||||||
|
{
|
||||||
|
namespace range_test_function
|
||||||
|
{
|
||||||
|
struct true_predicate
|
||||||
|
{
|
||||||
|
typedef bool result_type;
|
||||||
|
|
||||||
|
bool operator()() const { return true; }
|
||||||
|
template<class Arg> bool operator()(Arg) const { return true; }
|
||||||
|
template<class Arg1, class Arg2> bool operator()(Arg1,Arg2) const { return true; }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // include guard
|
Reference in New Issue
Block a user