1 //  result_of_tests.cpp  -- The Boost Lambda Library ------------------
2 //
3 // Copyright (C) 2010 Steven Watanabe
4 //
5 // Distributed under the Boost Software License, Version 1.0. (See
6 // accompanying file LICENSE_1_0.txt or copy at
7 // http://www.boost.org/LICENSE_1_0.txt)
8 //
9 // For more information, see www.boost.org
10 
11 // -----------------------------------------------------------------------
12 
13 
14 #include <boost/core/lightweight_test.hpp>
15 #include <boost/lambda/bind.hpp>
16 #include <boost/lambda/lambda.hpp>
17 #include <boost/mpl/assert.hpp>
18 #include <boost/type_traits/is_same.hpp>
19 
20 struct with_result_type {
21     typedef int result_type;
operator ()with_result_type22     int operator()() const { return 0; }
operator ()with_result_type23     int operator()(int) const { return 1; }
operator ()with_result_type24     int operator()(int, int) const { return 2; }
operator ()with_result_type25     int operator()(int, int, int) const { return 3; }
operator ()with_result_type26     int operator()(int, int, int, int) const { return 4; }
operator ()with_result_type27     int operator()(int, int, int, int, int) const { return 5; }
operator ()with_result_type28     int operator()(int, int, int, int, int, int) const { return 6; }
operator ()with_result_type29     int operator()(int, int, int, int, int, int, int) const { return 7; }
operator ()with_result_type30     int operator()(int, int, int, int, int, int, int, int) const { return 8; }
operator ()with_result_type31     int operator()(int, int, int, int, int, int, int, int, int) const { return 9; }
32 };
33 
34 struct with_result_template_value {
35     template<class Sig>
36     struct result;
37     template<class This>
38     struct result<This()> {
39         typedef int type;
40     };
41     template<class This, class A1>
42     struct result<This(A1)> {
43         BOOST_MPL_ASSERT((boost::is_same<A1, int>));
44         typedef int type;
45     };
46     template<class This, class A1, class A2>
47     struct result<This(A1, A2)> {
48         BOOST_MPL_ASSERT((boost::is_same<A1, int>));
49         BOOST_MPL_ASSERT((boost::is_same<A2, int>));
50         typedef int type;
51     };
52     template<class This, class A1, class A2, class A3>
53     struct result<This(A1, A2, A3)> {
54         BOOST_MPL_ASSERT((boost::is_same<A1, int>));
55         BOOST_MPL_ASSERT((boost::is_same<A2, int>));
56         BOOST_MPL_ASSERT((boost::is_same<A3, int>));
57         typedef int type;
58     };
59     template<class This, class A1, class A2, class A3, class A4>
60     struct result<This(A1, A2, A3, A4)> {
61         BOOST_MPL_ASSERT((boost::is_same<A1, int>));
62         BOOST_MPL_ASSERT((boost::is_same<A2, int>));
63         BOOST_MPL_ASSERT((boost::is_same<A3, int>));
64         BOOST_MPL_ASSERT((boost::is_same<A4, int>));
65         typedef int type;
66     };
67     template<class This, class A1, class A2, class A3, class A4, class A5>
68     struct result<This(A1, A2, A3, A4, A5)> {
69         BOOST_MPL_ASSERT((boost::is_same<A1, int>));
70         BOOST_MPL_ASSERT((boost::is_same<A2, int>));
71         BOOST_MPL_ASSERT((boost::is_same<A3, int>));
72         BOOST_MPL_ASSERT((boost::is_same<A4, int>));
73         BOOST_MPL_ASSERT((boost::is_same<A5, int>));
74         typedef int type;
75     };
76     template<class This, class A1, class A2, class A3, class A4, class A5, class A6>
77     struct result<This(A1, A2, A3, A4, A5, A6)> {
78         BOOST_MPL_ASSERT((boost::is_same<A1, int>));
79         BOOST_MPL_ASSERT((boost::is_same<A2, int>));
80         BOOST_MPL_ASSERT((boost::is_same<A3, int>));
81         BOOST_MPL_ASSERT((boost::is_same<A4, int>));
82         BOOST_MPL_ASSERT((boost::is_same<A5, int>));
83         BOOST_MPL_ASSERT((boost::is_same<A6, int>));
84         typedef int type;
85     };
86     template<class This, class A1, class A2, class A3, class A4, class A5, class A6, class A7>
87     struct result<This(A1, A2, A3, A4, A5, A6, A7)> {
88         BOOST_MPL_ASSERT((boost::is_same<A1, int>));
89         BOOST_MPL_ASSERT((boost::is_same<A2, int>));
90         BOOST_MPL_ASSERT((boost::is_same<A3, int>));
91         BOOST_MPL_ASSERT((boost::is_same<A4, int>));
92         BOOST_MPL_ASSERT((boost::is_same<A5, int>));
93         BOOST_MPL_ASSERT((boost::is_same<A6, int>));
94         BOOST_MPL_ASSERT((boost::is_same<A7, int>));
95         typedef int type;
96     };
97     template<class This, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8>
98     struct result<This(A1, A2, A3, A4, A5, A6, A7, A8)> {
99         BOOST_MPL_ASSERT((boost::is_same<A1, int>));
100         BOOST_MPL_ASSERT((boost::is_same<A2, int>));
101         BOOST_MPL_ASSERT((boost::is_same<A3, int>));
102         BOOST_MPL_ASSERT((boost::is_same<A4, int>));
103         BOOST_MPL_ASSERT((boost::is_same<A5, int>));
104         BOOST_MPL_ASSERT((boost::is_same<A6, int>));
105         BOOST_MPL_ASSERT((boost::is_same<A7, int>));
106         BOOST_MPL_ASSERT((boost::is_same<A8, int>));
107         typedef int type;
108     };
109     template<class This, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9>
110     struct result<This(A1, A2, A3, A4, A5, A6, A7, A8, A9)> {
111         BOOST_MPL_ASSERT((boost::is_same<A1, int>));
112         BOOST_MPL_ASSERT((boost::is_same<A2, int>));
113         BOOST_MPL_ASSERT((boost::is_same<A3, int>));
114         BOOST_MPL_ASSERT((boost::is_same<A4, int>));
115         BOOST_MPL_ASSERT((boost::is_same<A5, int>));
116         BOOST_MPL_ASSERT((boost::is_same<A6, int>));
117         BOOST_MPL_ASSERT((boost::is_same<A7, int>));
118         BOOST_MPL_ASSERT((boost::is_same<A8, int>));
119         BOOST_MPL_ASSERT((boost::is_same<A9, int>));
120         typedef int type;
121     };
122 
operator ()with_result_template_value123     int operator()() const { return 0; }
operator ()with_result_template_value124     int operator()(int) const { return 1; }
operator ()with_result_template_value125     int operator()(int, int) const { return 2; }
operator ()with_result_template_value126     int operator()(int, int, int) const { return 3; }
operator ()with_result_template_value127     int operator()(int, int, int, int) const { return 4; }
operator ()with_result_template_value128     int operator()(int, int, int, int, int) const { return 5; }
operator ()with_result_template_value129     int operator()(int, int, int, int, int, int) const { return 6; }
operator ()with_result_template_value130     int operator()(int, int, int, int, int, int, int) const { return 7; }
operator ()with_result_template_value131     int operator()(int, int, int, int, int, int, int, int) const { return 8; }
operator ()with_result_template_value132     int operator()(int, int, int, int, int, int, int, int, int) const { return 9; }
133 };
134 
135 struct with_result_template_reference {
136     template<class Sig>
137     struct result;
138     template<class This>
139     struct result<This()> {
140         typedef int type;
141     };
142     template<class This, class A1>
143     struct result<This(A1)> {
144         BOOST_MPL_ASSERT((boost::is_same<A1, int&>));
145         typedef int type;
146     };
147     template<class This, class A1, class A2>
148     struct result<This(A1, A2)> {
149         BOOST_MPL_ASSERT((boost::is_same<A1, int&>));
150         BOOST_MPL_ASSERT((boost::is_same<A2, int&>));
151         typedef int type;
152     };
153     template<class This, class A1, class A2, class A3>
154     struct result<This(A1, A2, A3)> {
155         BOOST_MPL_ASSERT((boost::is_same<A1, int&>));
156         BOOST_MPL_ASSERT((boost::is_same<A2, int&>));
157         BOOST_MPL_ASSERT((boost::is_same<A3, int&>));
158         typedef int type;
159     };
160     template<class This, class A1, class A2, class A3, class A4>
161     struct result<This(A1, A2, A3, A4)> {
162         BOOST_MPL_ASSERT((boost::is_same<A1, int&>));
163         BOOST_MPL_ASSERT((boost::is_same<A2, int&>));
164         BOOST_MPL_ASSERT((boost::is_same<A3, int&>));
165         BOOST_MPL_ASSERT((boost::is_same<A4, int&>));
166         typedef int type;
167     };
168     template<class This, class A1, class A2, class A3, class A4, class A5>
169     struct result<This(A1, A2, A3, A4, A5)> {
170         BOOST_MPL_ASSERT((boost::is_same<A1, int&>));
171         BOOST_MPL_ASSERT((boost::is_same<A2, int&>));
172         BOOST_MPL_ASSERT((boost::is_same<A3, int&>));
173         BOOST_MPL_ASSERT((boost::is_same<A4, int&>));
174         BOOST_MPL_ASSERT((boost::is_same<A5, int&>));
175         typedef int type;
176     };
177     template<class This, class A1, class A2, class A3, class A4, class A5, class A6>
178     struct result<This(A1, A2, A3, A4, A5, A6)> {
179         BOOST_MPL_ASSERT((boost::is_same<A1, int&>));
180         BOOST_MPL_ASSERT((boost::is_same<A2, int&>));
181         BOOST_MPL_ASSERT((boost::is_same<A3, int&>));
182         BOOST_MPL_ASSERT((boost::is_same<A4, int&>));
183         BOOST_MPL_ASSERT((boost::is_same<A5, int&>));
184         BOOST_MPL_ASSERT((boost::is_same<A6, int&>));
185         typedef int type;
186     };
187     template<class This, class A1, class A2, class A3, class A4, class A5, class A6, class A7>
188     struct result<This(A1, A2, A3, A4, A5, A6, A7)> {
189         BOOST_MPL_ASSERT((boost::is_same<A1, int&>));
190         BOOST_MPL_ASSERT((boost::is_same<A2, int&>));
191         BOOST_MPL_ASSERT((boost::is_same<A3, int&>));
192         BOOST_MPL_ASSERT((boost::is_same<A4, int&>));
193         BOOST_MPL_ASSERT((boost::is_same<A5, int&>));
194         BOOST_MPL_ASSERT((boost::is_same<A6, int&>));
195         BOOST_MPL_ASSERT((boost::is_same<A7, int&>));
196         typedef int type;
197     };
198     template<class This, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8>
199     struct result<This(A1, A2, A3, A4, A5, A6, A7, A8)> {
200         BOOST_MPL_ASSERT((boost::is_same<A1, int&>));
201         BOOST_MPL_ASSERT((boost::is_same<A2, int&>));
202         BOOST_MPL_ASSERT((boost::is_same<A3, int&>));
203         BOOST_MPL_ASSERT((boost::is_same<A4, int&>));
204         BOOST_MPL_ASSERT((boost::is_same<A5, int&>));
205         BOOST_MPL_ASSERT((boost::is_same<A6, int&>));
206         BOOST_MPL_ASSERT((boost::is_same<A7, int&>));
207         BOOST_MPL_ASSERT((boost::is_same<A8, int&>));
208         typedef int type;
209     };
210     template<class This, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9>
211     struct result<This(A1, A2, A3, A4, A5, A6, A7, A8, A9)> {
212         BOOST_MPL_ASSERT((boost::is_same<A1, int&>));
213         BOOST_MPL_ASSERT((boost::is_same<A2, int&>));
214         BOOST_MPL_ASSERT((boost::is_same<A3, int&>));
215         BOOST_MPL_ASSERT((boost::is_same<A4, int&>));
216         BOOST_MPL_ASSERT((boost::is_same<A5, int&>));
217         BOOST_MPL_ASSERT((boost::is_same<A6, int&>));
218         BOOST_MPL_ASSERT((boost::is_same<A7, int&>));
219         BOOST_MPL_ASSERT((boost::is_same<A8, int&>));
220         BOOST_MPL_ASSERT((boost::is_same<A9, int&>));
221         typedef int type;
222     };
223 
operator ()with_result_template_reference224     int operator()() const { return 0; }
operator ()with_result_template_reference225     int operator()(int) const { return 1; }
operator ()with_result_template_reference226     int operator()(int, int) const { return 2; }
operator ()with_result_template_reference227     int operator()(int, int, int) const { return 3; }
operator ()with_result_template_reference228     int operator()(int, int, int, int) const { return 4; }
operator ()with_result_template_reference229     int operator()(int, int, int, int, int) const { return 5; }
operator ()with_result_template_reference230     int operator()(int, int, int, int, int, int) const { return 6; }
operator ()with_result_template_reference231     int operator()(int, int, int, int, int, int, int) const { return 7; }
operator ()with_result_template_reference232     int operator()(int, int, int, int, int, int, int, int) const { return 8; }
operator ()with_result_template_reference233     int operator()(int, int, int, int, int, int, int, int, int) const { return 9; }
234 };
235 
236 template<class F>
apply0(F f)237 typename boost::result_of<F()>::type apply0(F f) {
238     return f();
239 }
240 template<class A, class F>
apply1(F f,A a)241 typename boost::result_of<F(A)>::type apply1(F f, A a) {
242     return f(a);
243 }
244 template<class A, class B, class F>
apply2(F f,A a,B b)245 typename boost::result_of<F(A, B)>::type apply2(F f, A a, B b) {
246     return f(a, b);
247 }
248 template<class A, class B, class C, class F>
apply3(F f,A a,B b,C c)249 typename boost::result_of<F(A, B, C)>::type apply3(F f, A a, B b, C c) {
250     return f(a, b, c);
251 }
252 
253 using namespace boost::lambda;
254 
main()255 int main()
256 {
257     BOOST_TEST_EQ(boost::lambda::bind(with_result_type())(), 0);
258     BOOST_TEST_EQ(boost::lambda::bind(with_result_type(), 1)(), 1);
259     BOOST_TEST_EQ(boost::lambda::bind(with_result_type(), 1, 2)(), 2);
260     BOOST_TEST_EQ(boost::lambda::bind(with_result_type(), 1, 2, 3)(), 3);
261     BOOST_TEST_EQ(boost::lambda::bind(with_result_type(), 1, 2, 3, 4)(), 4);
262     BOOST_TEST_EQ(boost::lambda::bind(with_result_type(), 1, 2, 3, 4, 5)(), 5);
263     BOOST_TEST_EQ(boost::lambda::bind(with_result_type(), 1, 2, 3, 4, 5, 6)(), 6);
264     BOOST_TEST_EQ(boost::lambda::bind(with_result_type(), 1, 2, 3, 4, 5, 6, 7)(), 7);
265     BOOST_TEST_EQ(boost::lambda::bind(with_result_type(), 1, 2, 3, 4, 5, 6, 7, 8)(), 8);
266     BOOST_TEST_EQ(boost::lambda::bind(with_result_type(), 1, 2, 3, 4, 5, 6, 7, 8, 9)(), 9);
267 
268     // Nullary result_of fails
269     //BOOST_TEST_EQ(boost::lambda::bind(with_result_template_value())(), 0);
270     BOOST_TEST_EQ(boost::lambda::bind(with_result_template_value(), 1)(), 1);
271     BOOST_TEST_EQ(boost::lambda::bind(with_result_template_value(), 1, 2)(), 2);
272     BOOST_TEST_EQ(boost::lambda::bind(with_result_template_value(), 1, 2, 3)(), 3);
273     BOOST_TEST_EQ(boost::lambda::bind(with_result_template_value(), 1, 2, 3, 4)(), 4);
274     BOOST_TEST_EQ(boost::lambda::bind(with_result_template_value(), 1, 2, 3, 4, 5)(), 5);
275     BOOST_TEST_EQ(boost::lambda::bind(with_result_template_value(), 1, 2, 3, 4, 5, 6)(), 6);
276     BOOST_TEST_EQ(boost::lambda::bind(with_result_template_value(), 1, 2, 3, 4, 5, 6, 7)(), 7);
277     BOOST_TEST_EQ(boost::lambda::bind(with_result_template_value(), 1, 2, 3, 4, 5, 6, 7, 8)(), 8);
278     BOOST_TEST_EQ(boost::lambda::bind(with_result_template_value(), 1, 2, 3, 4, 5, 6, 7, 8, 9)(), 9);
279 
280     int one = 1,
281         two = 2,
282         three = 3,
283         four = 4,
284         five = 5,
285         six = 6,
286         seven = 7,
287         eight = 8,
288         nine = 9;
289 
290     // Nullary result_of fails
291     //BOOST_TEST_EQ(boost::lambda::bind(with_result_template_reference())(), 0);
292     BOOST_TEST_EQ(boost::lambda::bind(with_result_template_reference(), var(one))(), 1);
293     BOOST_TEST_EQ(boost::lambda::bind(with_result_template_reference(), var(one), var(two))(), 2);
294     BOOST_TEST_EQ(boost::lambda::bind(with_result_template_reference(), var(one), var(two), var(three))(), 3);
295     BOOST_TEST_EQ(boost::lambda::bind(with_result_template_reference(), var(one), var(two), var(three), var(four))(), 4);
296     BOOST_TEST_EQ(boost::lambda::bind(with_result_template_reference(), var(one), var(two), var(three), var(four), var(five))(), 5);
297     BOOST_TEST_EQ(boost::lambda::bind(with_result_template_reference(), var(one), var(two), var(three), var(four), var(five), var(six))(), 6);
298     BOOST_TEST_EQ(boost::lambda::bind(with_result_template_reference(), var(one), var(two), var(three), var(four), var(five), var(six), var(seven))(), 7);
299     BOOST_TEST_EQ(boost::lambda::bind(with_result_template_reference(), var(one), var(two), var(three), var(four), var(five), var(six), var(seven), var(eight))(), 8);
300     BOOST_TEST_EQ(boost::lambda::bind(with_result_template_reference(), var(one), var(two), var(three), var(four), var(five), var(six), var(seven), var(eight), var(nine))(), 9);
301 
302     // Check using result_of with lambda functors
303     //BOOST_TEST_EQ(apply0(constant(0)), 0);
304     BOOST_TEST_EQ(apply1<int>(_1, one), 1);
305     BOOST_TEST_EQ(apply1<int&>(_1, one), 1);
306     BOOST_TEST_EQ(apply1<const int&>(_1, one), 1);
307     BOOST_TEST_EQ((apply2<int, int>(_1 + _2, one, two)), 3);
308     BOOST_TEST_EQ((apply2<int&, int&>(_1 + _2, one, two)), 3);
309     BOOST_TEST_EQ((apply2<const int&, const int&>(_1 + _2, one, two)), 3);
310     BOOST_TEST_EQ((apply3<int, int, int>(_1 + _2 + _3, one, two, three)), 6);
311     BOOST_TEST_EQ((apply3<int&, int&, int&>(_1 + _2 + _3, one, two, three)), 6);
312     BOOST_TEST_EQ((apply3<const int&, const int&, const int&>(_1 + _2 + _3, one, two, three)), 6);
313 
314     return boost::report_errors();
315 }
316