summaryrefslogtreecommitdiffstats
path: root/src/boost/libs/move/test/copy_move_optimization.cpp
blob: 06d184756ba2f30d2bd4f4e7de8f9db8ce81256b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
//We need to declare:
//
//2 conversions: rv<T> & and const rv<T> &
//1 rv<T> & constructor: move constructor
//1 const rv<T> & constructor: copy constructor
//1 T & constructor: copy constructor
//
//Optimization:
//Since RVO is better than move-construction,
//avoid copy constructor overloading.
#include <boost/move/detail/config_begin.hpp>
#include <boost/move/utility_core.hpp>
#include <iostream>

bool moved = false;

class obj
{
   BOOST_COPYABLE_AND_MOVABLE(obj)
   public:

   obj()
   {
      std::cout << "constructing obj" << "\n";
   }

   ~obj()
   {}

   obj(const obj &)
   {
      std::cout << "copy construct from const obj" << "\n";
   }

   // copy construct from movable object (non-const rvalue, explicitly moved lvalue)
   obj(BOOST_RV_REF(obj))
   {
      std::cout << "move construct from movable rvalue" << "\n";
   }

   obj& operator =(BOOST_COPY_ASSIGN_REF(obj))
   {
      std::cout << "copy assign from const obj" << "\n";
      return *this;
   }

   obj& operator =(BOOST_RV_REF(obj))
   {
      std::cout << "move assign from movable rvalue" << "\n";
      return *this;
   }
};


obj        rvalue_func()       { return obj(); }
const obj  const_rvalue_func() { return obj();  }
obj&       lvalue_func()       { static obj o;  return o; }
const obj& const_lvalue_func() { static obj o; return o; }

obj produce()     { return obj(); }

void consume(obj){}

int main()
{
   {  consume(produce());  }
   {  obj o = produce();   }
   {  obj o(produce());    }
   {
   obj o1(rvalue_func());
   obj o2 = const_rvalue_func();
   obj o3 = lvalue_func();
   obj o4 = const_lvalue_func();
   // can't explicitly move temporaries
   //obj o5 = boost::move(rvalue_func());
   obj o5;
   //Maybe missed optimization: copied
   o5 = rvalue_func();
   //Explicit forward works OK and optimized
   o5 = boost::forward<obj>(rvalue_func());

   obj o7 = boost::move(lvalue_func());
   obj o8 = boost::move(const_lvalue_func());

   obj o;
   o = rvalue_func();
   o = const_rvalue_func();
   o = lvalue_func();
   o = const_lvalue_func();
   // can't explicitly move temporaries
   //o = boost::move(rvalue_func());
   o = boost::forward<obj>(rvalue_func());
   o = boost::move(const_rvalue_func());
   o = boost::move(lvalue_func());
   o = boost::move(const_lvalue_func());
   }
   return 0;
}

//We need to declare:
//
//2 conversions: rv<T> & and const rv<T> &
//1 rv<T> & constructor: move constructor
//1 const rv<T> & constructor: copy constructor
//1 T & constructor: copy constructor

#include <boost/move/detail/config_end.hpp>