1 | // Copyright 2014 Antony Polukhin. |
2 | // |
3 | // Distributed under the Boost Software License, Version 1.0. |
4 | // (See accompanying file LICENSE_1_0.txt |
5 | // or copy at http://www.boost.org/LICENSE_1_0.txt) |
6 | |
7 | // For more information, see http://www.boost.org |
8 | |
9 | #include <boost/function.hpp> |
10 | #include <boost/move/move.hpp> |
11 | #include <boost/core/lightweight_test.hpp> |
12 | #include <iostream> |
13 | #include <cstdlib> |
14 | |
15 | #define BOOST_CHECK BOOST_TEST |
16 | |
17 | class only_movable { |
18 | private: |
19 | BOOST_MOVABLE_BUT_NOT_COPYABLE(only_movable) |
20 | int value_; |
21 | bool moved_; |
22 | |
23 | public: |
24 | only_movable(BOOST_RV_REF(only_movable) x) |
25 | : value_(x.value_) |
26 | , moved_(false) |
27 | { |
28 | x.moved_ = true; |
29 | } |
30 | |
31 | only_movable& operator=(BOOST_RV_REF(only_movable) x) { |
32 | value_ = x.value_; |
33 | x.moved_ = true; |
34 | moved_ = false; |
35 | return *this; |
36 | } |
37 | |
38 | explicit only_movable(int value = 0) : value_(value), moved_(false) {} |
39 | int get_value() const { return value_; } |
40 | bool is_moved() const { return moved_; } |
41 | }; |
42 | |
43 | |
44 | int one(BOOST_RV_REF(only_movable) v) { return v.get_value(); } |
45 | only_movable two(BOOST_RV_REF(only_movable) t) { |
46 | only_movable t1 = boost::move(t); |
47 | return BOOST_MOVE_RET(only_movable, t1); |
48 | } |
49 | |
50 | only_movable two_sum(BOOST_RV_REF(only_movable) t1, BOOST_RV_REF(only_movable) t2) { |
51 | only_movable ret(t1.get_value() + t2.get_value()); |
52 | return BOOST_MOVE_RET(only_movable, ret); |
53 | } |
54 | |
55 | struct sum_struct { |
56 | only_movable operator()(BOOST_RV_REF(only_movable) t1, BOOST_RV_REF(only_movable) t2) const { |
57 | only_movable ret(t1.get_value() + t2.get_value()); |
58 | return BOOST_MOVE_RET(only_movable, ret); |
59 | } |
60 | }; |
61 | |
62 | int three(std::string&&) { return 1; } |
63 | std::string&& four(std::string&& s) { return boost::move(t&: s); } |
64 | |
65 | int main() |
66 | { |
67 | using boost::function; |
68 | |
69 | function <int(BOOST_RV_REF(only_movable))> f1 = one; |
70 | |
71 | only_movable om1(1); |
72 | BOOST_CHECK(f1(boost::move(om1)) == 1); |
73 | |
74 | function <only_movable(BOOST_RV_REF(only_movable))> f2 = two; |
75 | |
76 | only_movable om2(2); |
77 | only_movable om2_2 = f2(boost::move(t&: om2)); |
78 | BOOST_CHECK(om2_2.get_value() == 2); |
79 | BOOST_CHECK(om2.is_moved()); |
80 | |
81 | { |
82 | function <only_movable(BOOST_RV_REF(only_movable), BOOST_RV_REF(only_movable))> f2_sum = two_sum; |
83 | only_movable om1_sum(1), om2_sum(2); |
84 | only_movable om2_sum_2 = f2_sum(boost::move(t&: om1_sum), boost::move(t&: om2_sum)); |
85 | BOOST_CHECK(om2_sum_2.get_value() == 3); |
86 | } |
87 | |
88 | { |
89 | sum_struct s; |
90 | function <only_movable(BOOST_RV_REF(only_movable), BOOST_RV_REF(only_movable))> f2_sum = s; |
91 | only_movable om1_sum(1), om2_sum(2); |
92 | only_movable om2_sum_2 = f2_sum(boost::move(t&: om1_sum), boost::move(t&: om2_sum)); |
93 | BOOST_CHECK(om2_sum_2.get_value() == 3); |
94 | } |
95 | |
96 | function <int(std::string&&)> f3 = three; |
97 | function <std::string&& (std::string&& s)> f4 = four; |
98 | |
99 | f3(std::string("Hello" )); |
100 | BOOST_CHECK(f4(std::string("world" )) == "world" ); |
101 | |
102 | return boost::report_errors(); |
103 | } |
104 | |