~ubuntu-branches/debian/sid/boost1.49/sid

« back to all changes in this revision

Viewing changes to libs/move/test/copy_elision_test.cpp

  • Committer: Package Import Robot
  • Author(s): Steve M. Robbins
  • Date: 2012-02-26 00:31:44 UTC
  • Revision ID: package-import@ubuntu.com-20120226003144-eaytp12cbf6ubpms
Tags: upstream-1.49.0
ImportĀ upstreamĀ versionĀ 1.49.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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)
 
4
 
 
5
#include <iostream>
 
6
 
 
7
#ifdef NO_MOVE
 
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)
 
12
# define MOVE(x) (x)
 
13
#else
 
14
#include <boost/move/move.hpp>
 
15
# define MOVE(x) boost::move(x)
 
16
#endif
 
17
 
 
18
struct X
 
19
{
 
20
    X() : id(instances++)
 
21
    {
 
22
        std::cout << "X" << id << ": construct\n";
 
23
    }
 
24
    
 
25
    X(X const& rhs) : id(instances++)
 
26
    {
 
27
        std::cout << "X" << id << ": <- " << "X" << rhs.id << ": **copy**\n";
 
28
        ++copies;
 
29
    }
 
30
 
 
31
    // This particular test doesn't exercise assignment, but for
 
32
    // completeness:
 
33
    X& operator=(BOOST_COPY_ASSIGN_REF(X) rhs)
 
34
    {
 
35
        std::cout << "X" << id << ": <- " << "X" << rhs.id << ": assign\n";
 
36
        return *this;
 
37
    }
 
38
 
 
39
#ifndef NO_MOVE
 
40
    X& operator=(BOOST_RV_REF(X) rhs)
 
41
    {
 
42
        std::cout << "X" << id << ": <- " << "X" << rhs.id << ": move assign\n";
 
43
        return *this;
 
44
    }
 
45
    
 
46
    X(BOOST_RV_REF(X) rhs) : id(instances++)
 
47
    {
 
48
        std::cout << "X" << id << ": <- " << "X" << rhs.id << ": ..move construct..\n";
 
49
        ++copies;
 
50
    }
 
51
#endif 
 
52
 
 
53
    ~X() { std::cout << "X" << id << ": destroy\n"; }
 
54
 
 
55
    unsigned id;
 
56
    
 
57
    static unsigned copies;
 
58
    static unsigned instances;
 
59
 
 
60
    BOOST_COPYABLE_AND_MOVABLE(X)
 
61
};
 
62
 
 
63
unsigned X::copies = 0;
 
64
unsigned X::instances = 0;
 
65
 
 
66
#define CHECK_COPIES( stmt, min, max, comment )                         \
 
67
{                                                                       \
 
68
    unsigned const old_copies = X::copies;                              \
 
69
                                                                        \
 
70
    std::cout << "\n" comment "\n" #stmt "\n===========\n";             \
 
71
    {                                                                   \
 
72
        stmt;                                                           \
 
73
    }                                                                   \
 
74
    unsigned const n = X::copies - old_copies;                          \
 
75
    if (n > max)                                                        \
 
76
        std::cout << "*** max is too low or compiler is buggy ***\n";   \
 
77
    if (n < min)                                                        \
 
78
        std::cout << "*** min is too high or compiler is buggy ***\n";  \
 
79
                                                                        \
 
80
    std::cout << "-----------\n"                                        \
 
81
              << n << "/" << max                                        \
 
82
              << " possible copies/moves made\n"                        \
 
83
              << max - n << "/" << max - min                            \
 
84
              << " possible elisions performed\n\n";                    \
 
85
                                                                        \
 
86
    if (n > min)                                                        \
 
87
        std::cout << "*** " << n - min                                  \
 
88
                  << " possible elisions missed! ***\n";                \
 
89
}
 
90
 
 
91
struct trace
 
92
{
 
93
    trace(char const* name)
 
94
        : name(name)
 
95
    {
 
96
        std::cout << "->: " << name << "\n";
 
97
    }
 
98
    
 
99
    ~trace()
 
100
    {
 
101
        std::cout << "<-: " << name << "\n";
 
102
    }
 
103
    
 
104
    char const* name;
 
105
};
 
106
 
 
107
void sink(X a)
 
108
{
 
109
  trace t("sink");
 
110
}
 
111
 
 
112
X nrvo_source()
 
113
{
 
114
    trace t("nrvo_source");
 
115
    X a;
 
116
    return a;
 
117
}
 
118
 
 
119
X urvo_source()
 
120
{
 
121
    trace t("urvo_source");
 
122
    return X();
 
123
}
 
124
 
 
125
X identity(X a)
 
126
{
 
127
    trace t("identity");
 
128
    return a;
 
129
}
 
130
 
 
131
X lvalue_;
 
132
X& lvalue()
 
133
{
 
134
    return lvalue_;
 
135
}
 
136
typedef X rvalue;
 
137
 
 
138
X ternary( bool y )
 
139
{
 
140
    X a, b;
 
141
    return MOVE(y?a:b);
 
142
}
 
143
 
 
144
int main(int argc, char* argv[])
 
145
{
 
146
   (void)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");
 
150
    
 
151
    CHECK_COPIES( X a = lvalue(), 1, 1, "Copy initialization from lvalue" );
 
152
    CHECK_COPIES( X a = rvalue(), 0, 1, "Copy initialization from rvalue" );
 
153
 
 
154
    CHECK_COPIES( sink( lvalue() ), 1, 1, "Pass lvalue by value" );
 
155
    CHECK_COPIES( sink( rvalue() ), 0, 1, "Pass rvalue by value" );
 
156
 
 
157
    CHECK_COPIES( nrvo_source(), 0, 1, "Named return value optimization (NRVO)" );
 
158
    CHECK_COPIES( urvo_source(), 0, 1, "Unnamed return value optimization (URVO)" );
 
159
 
 
160
    // Just to prove these things compose properly
 
161
    CHECK_COPIES( X a(urvo_source()), 0, 2, "Return value used as ctor arg" );
 
162
    
 
163
    // Expect to miss one possible elision here
 
164
    CHECK_COPIES( identity( rvalue() ), 0, 2, "Return rvalue passed by value" );
 
165
 
 
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" );
 
169
    return 0;
 
170
}