1
// Copyright David Abrahams 2009. Distributed under the Boost
2
// Software License, Version 1.0. (See accompanying
3
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
8
# undef BOOST_COPY_ASSIGN_REF
9
# define BOOST_COPY_ASSIGN_REF(X) X const&
10
# undef BOOST_COPYABLE_AND_MOVABLE
11
# define BOOST_COPYABLE_AND_MOVABLE(X)
14
#include <boost/move/move.hpp>
15
# define MOVE(x) boost::move(x)
22
std::cout << "X" << id << ": construct\n";
25
X(X const& rhs) : id(instances++)
27
std::cout << "X" << id << ": <- " << "X" << rhs.id << ": **copy**\n";
31
// This particular test doesn't exercise assignment, but for
33
X& operator=(BOOST_COPY_ASSIGN_REF(X) rhs)
35
std::cout << "X" << id << ": <- " << "X" << rhs.id << ": assign\n";
40
X& operator=(BOOST_RV_REF(X) rhs)
42
std::cout << "X" << id << ": <- " << "X" << rhs.id << ": move assign\n";
46
X(BOOST_RV_REF(X) rhs) : id(instances++)
48
std::cout << "X" << id << ": <- " << "X" << rhs.id << ": ..move construct..\n";
53
~X() { std::cout << "X" << id << ": destroy\n"; }
57
static unsigned copies;
58
static unsigned instances;
60
BOOST_COPYABLE_AND_MOVABLE(X)
63
unsigned X::copies = 0;
64
unsigned X::instances = 0;
66
#define CHECK_COPIES( stmt, min, max, comment ) \
68
unsigned const old_copies = X::copies; \
70
std::cout << "\n" comment "\n" #stmt "\n===========\n"; \
74
unsigned const n = X::copies - old_copies; \
76
std::cout << "*** max is too low or compiler is buggy ***\n"; \
78
std::cout << "*** min is too high or compiler is buggy ***\n"; \
80
std::cout << "-----------\n" \
82
<< " possible copies/moves made\n" \
83
<< max - n << "/" << max - min \
84
<< " possible elisions performed\n\n"; \
87
std::cout << "*** " << n - min \
88
<< " possible elisions missed! ***\n"; \
93
trace(char const* name)
96
std::cout << "->: " << name << "\n";
101
std::cout << "<-: " << name << "\n";
114
trace t("nrvo_source");
121
trace t("urvo_source");
144
int main(int argc, char* argv[])
147
// Double parens prevent "most vexing parse"
148
CHECK_COPIES( X a(( lvalue() )), 1, 1, "Direct initialization from lvalue");
149
CHECK_COPIES( X a(( rvalue() )), 0, 1, "Direct initialization from rvalue");
151
CHECK_COPIES( X a = lvalue(), 1, 1, "Copy initialization from lvalue" );
152
CHECK_COPIES( X a = rvalue(), 0, 1, "Copy initialization from rvalue" );
154
CHECK_COPIES( sink( lvalue() ), 1, 1, "Pass lvalue by value" );
155
CHECK_COPIES( sink( rvalue() ), 0, 1, "Pass rvalue by value" );
157
CHECK_COPIES( nrvo_source(), 0, 1, "Named return value optimization (NRVO)" );
158
CHECK_COPIES( urvo_source(), 0, 1, "Unnamed return value optimization (URVO)" );
160
// Just to prove these things compose properly
161
CHECK_COPIES( X a(urvo_source()), 0, 2, "Return value used as ctor arg" );
163
// Expect to miss one possible elision here
164
CHECK_COPIES( identity( rvalue() ), 0, 2, "Return rvalue passed by value" );
166
// Expect to miss an elision in at least one of the following lines
167
CHECK_COPIES( X a = ternary( argc == 1000 ), 0, 2, "Return result of ternary operation" );
168
CHECK_COPIES( X a = ternary( argc != 1000 ), 0, 2, "Return result of ternary operation again" );