1 // Copyright 2010 (c) Dean Michael Berris
2 // Distributed under the Boost Software License Version 1.0.
3 // (See accompanying file LICENSE_1_0.txt or copy at
4 // http://www.boost.org/LICENSE_1_0.txt)
5 
6 #include <cstddef>
7 
8 #include <algorithm>
9 #include <iterator>
10 #include <vector>
11 
12 #include <boost/config.hpp>
13 
14 #if !defined(BOOST_NO_CXX11_DECLTYPE)
15 // Force boost::result_of use decltype, even on compilers that don't support N3276.
16 // This enables this test to also verify if the iterator works with lambdas
17 // on such compilers with this config macro. Note that without the macro result_of
18 // (and consequently the iterator) is guaranteed to _not_ work, so this case is not
19 // worth testing anyway.
20 #define BOOST_RESULT_OF_USE_DECLTYPE
21 #endif
22 
23 #include <boost/core/lightweight_test.hpp>
24 #include <boost/iterator/function_input_iterator.hpp>
25 
26 namespace {
27 
28 struct ones {
29     typedef int result_type;
operator ()__anon82049ada0111::ones30     result_type operator() () {
31         return 1;
32     }
33 };
34 
ones_function()35 int ones_function () {
36     return 1;
37 }
38 
39 struct counter {
40     typedef int result_type;
41     int n;
counter__anon82049ada0111::counter42     explicit counter(int n_) : n(n_) { }
operator ()__anon82049ada0111::counter43     result_type operator() () {
44         return n++;
45     }
46 };
47 
48 } // namespace
49 
50 using namespace std;
51 
main()52 int main()
53 {
54     // test the iterator with function objects
55     ones ones_generator;
56     vector<int> values(10);
57     generate(values.begin(), values.end(), ones());
58 
59     vector<int> generated;
60     copy(
61         boost::make_function_input_iterator(ones_generator, 0),
62         boost::make_function_input_iterator(ones_generator, 10),
63         back_inserter(generated)
64         );
65 
66     BOOST_TEST_ALL_EQ(values.begin(), values.end(), generated.begin(), generated.end());
67 
68     // test the iterator with normal functions
69     vector<int>().swap(generated);
70     copy(
71         boost::make_function_input_iterator(&ones_function, 0),
72         boost::make_function_input_iterator(&ones_function, 10),
73         back_inserter(generated)
74         );
75 
76     BOOST_TEST_ALL_EQ(values.begin(), values.end(), generated.begin(), generated.end());
77 
78     // test the iterator with a reference to a function
79     vector<int>().swap(generated);
80     copy(
81         boost::make_function_input_iterator(ones_function, 0),
82         boost::make_function_input_iterator(ones_function, 10),
83         back_inserter(generated)
84         );
85 
86     BOOST_TEST_ALL_EQ(values.begin(), values.end(), generated.begin(), generated.end());
87 
88     // test the iterator with a stateful function object
89     counter counter_generator(42);
90     vector<int>().swap(generated);
91     copy(
92         boost::make_function_input_iterator(counter_generator, 0),
93         boost::make_function_input_iterator(counter_generator, 10),
94         back_inserter(generated)
95         );
96 
97     BOOST_TEST_EQ(generated.size(), 10u);
98     BOOST_TEST_EQ(counter_generator.n, 42 + 10);
99     for(std::size_t i = 0; i != 10; ++i)
100         BOOST_TEST_EQ(generated[i], static_cast<int>(42 + i));
101 
102 #if !defined(BOOST_NO_CXX11_LAMBDAS) && !defined(BOOST_NO_CXX11_AUTO_DECLARATIONS) \
103     && defined(BOOST_RESULT_OF_USE_DECLTYPE)
104     // test the iterator with lambda expressions
105     int num = 42;
106     auto lambda_generator = [&num] { return num++; };
107     vector<int>().swap(generated);
108     copy(
109         boost::make_function_input_iterator(lambda_generator, 0),
110         boost::make_function_input_iterator(lambda_generator, 10),
111         back_inserter(generated)
112         );
113 
114     BOOST_TEST_EQ(generated.size(), 10u);
115     for(std::size_t i = 0; i != 10; ++i)
116         BOOST_TEST_EQ(generated[i], static_cast<int>(42 + i));
117 #endif // BOOST_NO_CXX11_LAMBDAS
118 
119     return boost::report_errors();
120 }
121