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 <iostream>
10 #include <cstdlib>
11
12 #include <boost/test/minimal.hpp>
13 #include <boost/function.hpp>
14 #include <boost/move/move.hpp>
15
16 class only_movable {
17 private:
18 BOOST_MOVABLE_BUT_NOT_COPYABLE(only_movable)
19 int value_;
20 bool moved_;
21
22 public:
only_movable(BOOST_RV_REF (only_movable)x)23 only_movable(BOOST_RV_REF(only_movable) x)
24 : value_(x.value_)
25 , moved_(false)
26 {
27 x.moved_ = true;
28 }
29
operator =(BOOST_RV_REF (only_movable)x)30 only_movable& operator=(BOOST_RV_REF(only_movable) x) {
31 value_ = x.value_;
32 x.moved_ = true;
33 moved_ = false;
34 return *this;
35 }
36
only_movable(int value=0)37 explicit only_movable(int value = 0) : value_(value), moved_(false) {}
get_value() const38 int get_value() const { return value_; }
is_moved() const39 bool is_moved() const { return moved_; }
40 };
41
42
one(BOOST_RV_REF (only_movable)v)43 int one(BOOST_RV_REF(only_movable) v) { return v.get_value(); }
two(BOOST_RV_REF (only_movable)t)44 only_movable two(BOOST_RV_REF(only_movable) t) {
45 only_movable t1 = boost::move(t);
46 return BOOST_MOVE_RET(only_movable, t1);
47 }
48
two_sum(BOOST_RV_REF (only_movable)t1,BOOST_RV_REF (only_movable)t2)49 only_movable two_sum(BOOST_RV_REF(only_movable) t1, BOOST_RV_REF(only_movable) t2) {
50 only_movable ret(t1.get_value() + t2.get_value());
51 return BOOST_MOVE_RET(only_movable, ret);
52 }
53
54 struct sum_struct {
operator ()sum_struct55 only_movable operator()(BOOST_RV_REF(only_movable) t1, BOOST_RV_REF(only_movable) t2) const {
56 only_movable ret(t1.get_value() + t2.get_value());
57 return BOOST_MOVE_RET(only_movable, ret);
58 }
59 };
60
61 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
three(std::string &&)62 int three(std::string&&) { return 1; }
four(std::string && s)63 std::string&& four(std::string&& s) { return boost::move(s); }
64 #endif
65
test_main(int,char * [])66 int test_main(int, char*[])
67 {
68 using boost::function;
69
70 function <int(BOOST_RV_REF(only_movable))> f1 = one;
71
72 only_movable om1(1);
73 BOOST_CHECK(f1(boost::move(om1)) == 1);
74
75 function <only_movable(BOOST_RV_REF(only_movable))> f2 = two;
76
77 only_movable om2(2);
78 only_movable om2_2 = f2(boost::move(om2));
79 BOOST_CHECK(om2_2.get_value() == 2);
80 BOOST_CHECK(om2.is_moved());
81
82 {
83 function <only_movable(BOOST_RV_REF(only_movable), BOOST_RV_REF(only_movable))> f2_sum = two_sum;
84 only_movable om1_sum(1), om2_sum(2);
85 only_movable om2_sum_2 = f2_sum(boost::move(om1_sum), boost::move(om2_sum));
86 BOOST_CHECK(om2_sum_2.get_value() == 3);
87 }
88
89 {
90 sum_struct s;
91 function <only_movable(BOOST_RV_REF(only_movable), BOOST_RV_REF(only_movable))> f2_sum = s;
92 only_movable om1_sum(1), om2_sum(2);
93 only_movable om2_sum_2 = f2_sum(boost::move(om1_sum), boost::move(om2_sum));
94 BOOST_CHECK(om2_sum_2.get_value() == 3);
95 }
96
97 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
98 function <int(std::string&&)> f3 = three;
99 function <std::string&& (std::string&& s)> f4 = four;
100
101 f3(std::string("Hello"));
102 BOOST_CHECK(f4(std::string("world")) == "world");
103 #endif
104
105 return 0;
106 }
107