1 // Boost.Range library
2 //
3 // Copyright Neil Groves 2014. Use, modification and
4 // distribution is subject to the Boost Software License, Version
5 // 1.0. (See accompanying file LICENSE_1_0.txt or copy at
6 // http://www.boost.org/LICENSE_1_0.txt)
7 //
8 //
9 // For more information, see http://www.boost.org/libs/range/
10 //
11 // Credits:
12 // Jurgen Hunold provided a test case that demonstrated that the range adaptors
13 // were producing iterators that were not default constructible. This became
14 // symptomatic after enabling concept checking assertions. This test is a
15 // lightly modified version of his supplied code to ensure that his use case
16 // never breaks again. (hopefully!)
17 //
18
19 #include <boost/range/adaptor/transformed.hpp>
20 #include <boost/range/adaptor/filtered.hpp>
21 #include <boost/range/algorithm/copy.hpp>
22 #include <boost/bind/bind.hpp>
23
24 #include <boost/test/test_tools.hpp>
25 #include <boost/test/unit_test.hpp>
26
27 #include <vector>
28 #include <set>
29
30 namespace boost_range_test
31 {
32 namespace
33 {
34
35 class foo
36 {
37 public:
from_string(const std::string & source)38 static foo from_string(const std::string& source)
39 {
40 foo f;
41 f.m_valid = true;
42 f.m_value = 0u;
43 for (std::string::const_iterator it = source.begin();
44 it != source.end(); ++it)
45 {
46 f.m_value += *it;
47 if ((*it < 'a') || (*it > 'z'))
48 f.m_valid = false;
49 }
50 return f;
51 }
is_valid() const52 bool is_valid() const
53 {
54 return m_valid;
55 }
operator <(const foo & other) const56 bool operator<(const foo& other) const
57 {
58 return m_value < other.m_value;
59 }
operator ==(const foo & other) const60 bool operator==(const foo& other) const
61 {
62 return m_value == other.m_value && m_valid == other.m_valid;
63 }
operator !=(const foo & other) const64 bool operator!=(const foo& other) const
65 {
66 return !operator==(other);
67 }
68
operator <<(std::ostream & out,const foo & obj)69 friend inline std::ostream& operator<<(std::ostream& out, const foo& obj)
70 {
71 out << "{value=" << obj.m_value
72 << ", valid=" << std::boolalpha << obj.m_valid << "}\n";
73 return out;
74 }
75
76 private:
77 boost::uint64_t m_value;
78 bool m_valid;
79 };
80
chained_adaptors_test()81 void chained_adaptors_test()
82 {
83 std::vector<std::string> sep;
84
85 sep.push_back("AB");
86 sep.push_back("ab");
87 sep.push_back("aghj");
88
89 std::set<foo> foos;
90
91 using namespace boost::placeholders;
92
93 boost::copy(sep
94 | boost::adaptors::transformed(boost::bind(&foo::from_string, _1))
95 | boost::adaptors::filtered(boost::bind(&foo::is_valid, _1)),
96 std::inserter(foos, foos.end()));
97
98 std::vector<foo> reference;
99 reference.push_back(foo::from_string("ab"));
100 reference.push_back(foo::from_string("aghj"));
101
102 BOOST_CHECK_EQUAL_COLLECTIONS(
103 reference.begin(), reference.end(),
104 foos.begin(), foos.end());
105 }
106
107 } // anonymous namespace
108 } // namespace boost_range_test
109
110 boost::unit_test::test_suite*
init_unit_test_suite(int argc,char * argv[])111 init_unit_test_suite(int argc, char* argv[])
112 {
113 boost::unit_test::test_suite* test
114 = BOOST_TEST_SUITE( "RangeTestSuite.adaptor.chained adaptors" );
115
116 test->add(BOOST_TEST_CASE( boost_range_test::chained_adaptors_test));
117
118 return test;
119 }
120