GCC Code Coverage Report


Directory: ./
File: TestCopyElision.cpp
Date: 2026-03-21 20:51:59
Exec Total Coverage
Lines: 308 323 95.4%
Functions: 105 106 99.1%
Branches: 527 1422 37.1%

Line Branch Exec Source
1 // See [Copy elision](https://en.cppreference.com/w/cpp/language/copy_elision)
2 // See [Return value optimizations](https://www.fluentcpp.com/2016/11/28/return-value-optimizations/)
3 // See [Understanding when not to std::move in C++](https://developers.redhat.com/blog/2019/04/12/understanding-when-not-to-stdmove-in-c)
4 // See [How to Return Several Values from a Function in C++](https://www.fluentcpp.com/2021/07/09/how-to-return-several-values-from-a-function-in-c)
5
6 #include "Verbose.hpp"
7 #include <iostream>
8 #include <tuple>
9
10 // A class that can be moved but not copied.
11 class Uncopyable {
12 public:
13 4 Uncopyable() noexcept = default; // default constructor
14 Uncopyable(Uncopyable&&) noexcept = default; // move constructor
15 1 Uncopyable& operator=(Uncopyable&&) noexcept = default; // move assignment
16 8 virtual ~Uncopyable() noexcept = default; // destructor
17
18 Uncopyable(const Uncopyable&) = delete; // no copy constructor
19 Uncopyable& operator=(const Uncopyable&) = delete; // no copy assignment
20 };
21
22 // A class that can be copied but not moved.
23 class Unmovable {
24 public:
25 3 Unmovable() noexcept = default; // default constructor
26 Unmovable(const Unmovable&) = default; // copy constructor
27 1 Unmovable& operator=(const Unmovable&) = default; // copy assignment
28 6 virtual ~Unmovable() noexcept = default; // destructor
29
30 Unmovable(Unmovable&&) noexcept = delete; // no move constructor
31 Unmovable& operator=(Unmovable&&) noexcept = delete; // no move assignment
32 };
33
34 // An unrelated class that is convertible to Verbose.
35 class Convertible {
36 public:
37 2 operator Verbose<>() {
38 2 std::cout << "Convertible: conversion to Verbose this=" << this
39 2 << std::endl;
40
2/4
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
8 return Verbose<>{"Converted to Verbose"}; // rvo?
41 }
42 };
43
44 // A derived class.
45 class Derived : public Verbose<> {
46 public:
47 3 Derived() noexcept : Verbose<>{"Derived"} {}
48 };
49
50 // Unnamed value constructed in return statement.
51
2/4
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
8 Verbose<> rvo() { return Verbose<>{"unnamed"}; }
52
53 // Unnamed value constructed in return statement.
54 // Copy constructor need not be available.
55
2/4
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
4 Verbose<Uncopyable> rvo_uncopyable() { return Verbose<Uncopyable>{"unnamed"}; }
56
57 #if __cplusplus >= 201703L // since C++17
58
59 // Unnamed value constructed in return statement.
60 // Move constructor need not be available.
61
2/4
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
4 Verbose<Unmovable> rvo_unmovable() { return Verbose<Unmovable>{"unnamed"}; }
62
63 #endif // C++17
64
65 // Unnamed values constructed in all return statements.
66 1 Verbose<> rvo_conditional(int x) {
67
3/6
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
3 if (x % 2 == 0) { return Verbose<>{"even"}; }
68 else { return Verbose<>{"odd"}; }
69 }
70
71 // Unnamed value constructed from return value in return statement.
72 1 Verbose<> rvo_chained() { return Verbose<>{rvo()}; }
73
74 #if __cplusplus >= 201402L // since C++14
75
76 // Unnamed tuple of unnamed values constructed in return statement.
77 3 auto rvo_tuple() { return std::tuple<Verbose<>, Verbose<>>{"first", "second"}; }
78
79 #endif // C++14
80
81 // Unique named return value.
82 2 Verbose<> nrvo() {
83
2/4
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
6 auto result = Verbose<>{"unique"};
84 2 return result;
85 }
86
87 // Unique named movable return value.
88 // Copy constructor not available.
89 // How does this work ?!
90 1 Verbose<Uncopyable> nrvo_uncopyable() {
91
2/4
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
3 auto result = Verbose<Uncopyable>{"unique"};
92 1 return result;
93 }
94
95 // Unique named copyable return value.
96 // Fail! Move constructor not available! Does not compile!
97 /*
98 Unmovable nrvo_unmovable()
99 {
100 auto result Unmovable { "unique" };
101 return result;
102 }
103 */
104
105 // Unique named return value in all return statements.
106 1 Verbose<> nrvo_conditional(int x) {
107
2/4
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
3 auto result = Verbose<>{"unknown"};
108
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (x % 2 == 0) {
109 result.name() = "even";
110 return result;
111 }
112 else {
113
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 result.name() = "odd";
114 1 return result;
115 }
116 }
117
118 // Unique named return value constructed from return value.
119 1 Verbose<> nrvo_chained() {
120 1 auto result = Verbose<>{nrvo()};
121 1 return result;
122 }
123
124 #if __cplusplus >= 201402L // since C++14
125
126 // Unique named tuple return value.
127 2 auto nrvo_tuple_good() {
128 2 auto result = std::tuple<Verbose<>, Verbose<>>{"one", "two"};
129 2 auto& v1 = std::get<0>(result);
130 2 auto& v2 = std::get<1>(result);
131
1/2
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
2 v1.name() = "first";
132
1/2
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
2 v2.name() = "second";
133 2 return result;
134 }
135
136 #endif // C++14
137
138 #if __cplusplus >= 201703L // since C++17
139
140 // Unique named tuple return value.
141 2 auto nrvo_tuple_better() {
142 2 auto result = std::tuple<Verbose<>, Verbose<>>{"one", "two"};
143 2 auto& [v1, v2] = result;
144
1/2
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
2 v1.name() = "first";
145
1/2
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
2 v2.name() = "second";
146 2 return result;
147 }
148
149 #endif // C++17
150
151 #if __cplusplus >= 201402L // since C++14
152
153 // Fail! Named tuple of named values.
154 auto nrvo_tuple_bad() {
155 auto v1 = Verbose<>{"first"};
156 auto v2 = Verbose<>{"second"};
157 auto result = std::make_tuple(v1, v2);
158 return result;
159 }
160
161 // Unique named return value using a local, unnamed struct.
162 // Pros:
163 // + Returned values can have meaningful names, unlike std::tuple.
164 // + No need to unpack returned values with std::get or std::tie.
165 // + Works with structured binding, just like std::tuple.
166 // Cons:
167 // - Cannot be declared as a return type, unlike std::tuple,
168 // making the number of and types of returned values unclear.
169 // - Requires return type deduction. (C++14)
170 // * Cannot be used for virtual member functions.
171 // * Implemtation must be in same translation unit as declaration.
172 2 auto nrvo_struct() {
173 struct {
174 Verbose<> first{"first"};
175 Verbose<> second{"second"};
176 2 } result;
177 2 return result;
178 }
179
180 #endif // C++14
181
182 // Non-unique return values.
183 // This actually works with LLVM ?!
184 1 Verbose<> nrvo_not_unique(int x) {
185
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (x % 2 == 0) {
186 auto even = Verbose<>{"even"};
187 return even;
188 }
189 else {
190
2/4
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
3 auto odd = Verbose<>{"odd"};
191 1 return odd;
192 1 }
193 }
194
195 // Fail! Return value is function parameter.
196 1 Verbose<> nrvo_value_parameter(Verbose<> v) { return v; }
197
198 // Fail! Return value is function parameter.
199 1 Verbose<> nrvo_const_ref_parameter(const Verbose<>& v) { return v; }
200
201 // Fail! Return value is function parameter.
202 2 Verbose<> nrvo_move_parameter(Verbose<>&& v) { return std::move(v); }
203
204 // Fail! Unnamed value assigned to output parameter.
205 1 void rvo_output_parameter(Verbose<Uncopyable>& result) {
206
2/4
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
3 result = Verbose<Uncopyable>{"parameter"};
207 1 }
208
209 #if __cplusplus >= 201703L // since C++17
210
211 // Fail! Unique named value assigned to output parameter.
212 1 void nrvo_output_parameter(Verbose<Unmovable>& result) {
213
2/4
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
3 auto v = Verbose<Unmovable>{"parameter"};
214
1/2
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
1 result = v;
215 2 }
216
217 #endif // C++17
218
219 // Conversion operator is invoked implicitly.
220 // No copy or move operation is invoked, with or wihtout std::move().
221 // Using std::move() produces a GNU (but not LLVM) compiler warning.
222 1 Verbose<> implicit_conversion() {
223 1 auto c = Convertible{};
224
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
2 return c; // std::move() has no effect
225 }
226
227 // Conversion operator is invoked explicitly.
228 // No copy or move operation is invoked, with or without std::move().
229 // Using std::move() does not produce a compiler warning.
230 1 Verbose<> explicit_conversion() {
231 1 auto c = Convertible{};
232
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
2 return static_cast<Verbose<>>(c); // std::move() has no effect
233 }
234
235 // Convert to base type.
236 // Copy or move constructor is invoked, with or without std::move().
237 // Using std::move() produces a GNU (but not LLVM) compiler warning.
238 1 Verbose<> class_conversion() {
239 1 auto d = Derived{};
240 1 return d; // std::move() has no effect
241 1 }
242
243 ////////////////////////////////////////////////////////////////////////////////
244
245 #include <gmock/gmock.h>
246
247 using namespace testing;
248 using namespace testing::internal;
249
250 constexpr auto even_number{2};
251 constexpr auto odd_number{17};
252
253 8 TEST(CopyElision, rvo) {
254
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
2 CaptureStdout();
255
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
2 auto v = rvo();
256
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
2 auto actual = GetCapturedStdout();
257
7/20
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 11 taken 1 times.
✗ Branch 12 not taken.
✓ Branch 15 taken 1 times.
✗ Branch 16 not taken.
✓ Branch 18 taken 1 times.
✗ Branch 19 not taken.
✓ Branch 21 taken 1 times.
✗ Branch 22 not taken.
✓ Branch 24 taken 1 times.
✗ Branch 25 not taken.
✗ Branch 37 not taken.
✓ Branch 38 taken 1 times.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✗ Branch 47 not taken.
✗ Branch 48 not taken.
✗ Branch 51 not taken.
✗ Branch 52 not taken.
2 EXPECT_THAT(actual, Not(AnyOf(HasSubstr("copy"), HasSubstr("move"))));
258
3/6
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
2 std::cout << std::endl << actual << std::endl;
259 4 }
260
261 8 TEST(CopyElision, rvo_uncopyable) {
262
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
2 CaptureStdout();
263
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
2 auto u = rvo_uncopyable();
264
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
2 auto actual = GetCapturedStdout();
265
7/20
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 11 taken 1 times.
✗ Branch 12 not taken.
✓ Branch 15 taken 1 times.
✗ Branch 16 not taken.
✓ Branch 18 taken 1 times.
✗ Branch 19 not taken.
✓ Branch 21 taken 1 times.
✗ Branch 22 not taken.
✓ Branch 24 taken 1 times.
✗ Branch 25 not taken.
✗ Branch 37 not taken.
✓ Branch 38 taken 1 times.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✗ Branch 47 not taken.
✗ Branch 48 not taken.
✗ Branch 51 not taken.
✗ Branch 52 not taken.
2 EXPECT_THAT(actual, Not(AnyOf(HasSubstr("copy"), HasSubstr("move"))));
266
3/6
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
2 std::cout << std::endl << actual << std::endl;
267 4 }
268
269 #if __cplusplus >= 201703L // since C++17
270
271 8 TEST(CopyElision, rvo_unmovable) {
272
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
2 CaptureStdout();
273
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
2 auto u = rvo_unmovable();
274
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
2 auto actual = GetCapturedStdout();
275
7/20
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 11 taken 1 times.
✗ Branch 12 not taken.
✓ Branch 15 taken 1 times.
✗ Branch 16 not taken.
✓ Branch 18 taken 1 times.
✗ Branch 19 not taken.
✓ Branch 21 taken 1 times.
✗ Branch 22 not taken.
✓ Branch 24 taken 1 times.
✗ Branch 25 not taken.
✗ Branch 37 not taken.
✓ Branch 38 taken 1 times.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✗ Branch 47 not taken.
✗ Branch 48 not taken.
✗ Branch 51 not taken.
✗ Branch 52 not taken.
2 EXPECT_THAT(actual, Not(AnyOf(HasSubstr("copy"), HasSubstr("move"))));
276
3/6
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
2 std::cout << std::endl << actual << std::endl;
277 4 }
278
279 #endif // C++17
280
281 8 TEST(CopyElision, rvo_conditional) {
282
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
2 CaptureStdout();
283
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
2 auto v = rvo_conditional(even_number);
284
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
2 auto actual = GetCapturedStdout();
285
7/20
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 11 taken 1 times.
✗ Branch 12 not taken.
✓ Branch 15 taken 1 times.
✗ Branch 16 not taken.
✓ Branch 18 taken 1 times.
✗ Branch 19 not taken.
✓ Branch 21 taken 1 times.
✗ Branch 22 not taken.
✓ Branch 24 taken 1 times.
✗ Branch 25 not taken.
✗ Branch 37 not taken.
✓ Branch 38 taken 1 times.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✗ Branch 47 not taken.
✗ Branch 48 not taken.
✗ Branch 51 not taken.
✗ Branch 52 not taken.
2 EXPECT_THAT(actual, Not(AnyOf(HasSubstr("copy"), HasSubstr("move"))));
286
4/14
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 12 taken 1 times.
✗ Branch 13 not taken.
✗ Branch 19 not taken.
✓ Branch 20 taken 1 times.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
2 EXPECT_THAT(v.name(), StrEq("even"));
287
3/6
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
2 std::cout << std::endl << actual << std::endl;
288 4 }
289
290 8 TEST(CopyElision, rvo_chained) {
291
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
2 CaptureStdout();
292
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
2 auto v = rvo_chained();
293
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
2 auto actual = GetCapturedStdout();
294
7/20
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 11 taken 1 times.
✗ Branch 12 not taken.
✓ Branch 15 taken 1 times.
✗ Branch 16 not taken.
✓ Branch 18 taken 1 times.
✗ Branch 19 not taken.
✓ Branch 21 taken 1 times.
✗ Branch 22 not taken.
✓ Branch 24 taken 1 times.
✗ Branch 25 not taken.
✗ Branch 37 not taken.
✓ Branch 38 taken 1 times.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✗ Branch 47 not taken.
✗ Branch 48 not taken.
✗ Branch 51 not taken.
✗ Branch 52 not taken.
2 EXPECT_THAT(actual, Not(AnyOf(HasSubstr("copy"), HasSubstr("move"))));
295
3/6
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
2 std::cout << std::endl << actual << std::endl;
296 4 }
297
298 8 TEST(CopyElision, nrvo) {
299
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
2 CaptureStdout();
300
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
2 auto v = nrvo();
301
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
2 auto actual = GetCapturedStdout();
302
7/20
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 11 taken 1 times.
✗ Branch 12 not taken.
✓ Branch 15 taken 1 times.
✗ Branch 16 not taken.
✓ Branch 18 taken 1 times.
✗ Branch 19 not taken.
✓ Branch 21 taken 1 times.
✗ Branch 22 not taken.
✓ Branch 24 taken 1 times.
✗ Branch 25 not taken.
✗ Branch 37 not taken.
✓ Branch 38 taken 1 times.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✗ Branch 47 not taken.
✗ Branch 48 not taken.
✗ Branch 51 not taken.
✗ Branch 52 not taken.
2 EXPECT_THAT(actual, Not(AnyOf(HasSubstr("copy"), HasSubstr("move"))));
303
3/6
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
2 std::cout << std::endl << actual << std::endl;
304 4 }
305
306 8 TEST(CopyElision, nrvo_uncopyable) {
307
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
2 CaptureStdout();
308
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
2 auto v = nrvo_uncopyable();
309
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
2 auto actual = GetCapturedStdout();
310
7/20
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 11 taken 1 times.
✗ Branch 12 not taken.
✓ Branch 15 taken 1 times.
✗ Branch 16 not taken.
✓ Branch 18 taken 1 times.
✗ Branch 19 not taken.
✓ Branch 21 taken 1 times.
✗ Branch 22 not taken.
✓ Branch 24 taken 1 times.
✗ Branch 25 not taken.
✗ Branch 37 not taken.
✓ Branch 38 taken 1 times.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✗ Branch 47 not taken.
✗ Branch 48 not taken.
✗ Branch 51 not taken.
✗ Branch 52 not taken.
2 EXPECT_THAT(actual, Not(AnyOf(HasSubstr("copy"), HasSubstr("move"))));
311
3/6
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
2 std::cout << std::endl << actual << std::endl;
312 4 }
313
314 8 TEST(CopyElision, nrvo_conditional) {
315
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
2 CaptureStdout();
316
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
2 auto v = nrvo_conditional(odd_number);
317
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
2 auto actual = GetCapturedStdout();
318
7/20
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 11 taken 1 times.
✗ Branch 12 not taken.
✓ Branch 15 taken 1 times.
✗ Branch 16 not taken.
✓ Branch 18 taken 1 times.
✗ Branch 19 not taken.
✓ Branch 21 taken 1 times.
✗ Branch 22 not taken.
✓ Branch 24 taken 1 times.
✗ Branch 25 not taken.
✗ Branch 37 not taken.
✓ Branch 38 taken 1 times.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✗ Branch 47 not taken.
✗ Branch 48 not taken.
✗ Branch 51 not taken.
✗ Branch 52 not taken.
2 EXPECT_THAT(actual, Not(AnyOf(HasSubstr("copy"), HasSubstr("move"))));
319
4/14
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 12 taken 1 times.
✗ Branch 13 not taken.
✗ Branch 19 not taken.
✓ Branch 20 taken 1 times.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
2 EXPECT_THAT(v.name(), StrEq("odd"));
320
3/6
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
2 std::cout << std::endl << actual << std::endl;
321 4 }
322
323 8 TEST(CopyElision, nrvo_chained) {
324
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
2 CaptureStdout();
325
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
2 auto v = nrvo_chained();
326
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
2 auto actual = GetCapturedStdout();
327
7/20
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 11 taken 1 times.
✗ Branch 12 not taken.
✓ Branch 15 taken 1 times.
✗ Branch 16 not taken.
✓ Branch 18 taken 1 times.
✗ Branch 19 not taken.
✓ Branch 21 taken 1 times.
✗ Branch 22 not taken.
✓ Branch 24 taken 1 times.
✗ Branch 25 not taken.
✗ Branch 37 not taken.
✓ Branch 38 taken 1 times.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✗ Branch 47 not taken.
✗ Branch 48 not taken.
✗ Branch 51 not taken.
✗ Branch 52 not taken.
2 EXPECT_THAT(actual, Not(AnyOf(HasSubstr("copy"), HasSubstr("move"))));
328
3/6
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
2 std::cout << std::endl << actual << std::endl;
329 4 }
330
331 8 TEST(CopyElision, nrvo_not_unique) {
332
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
2 CaptureStdout();
333
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
2 auto v = nrvo_not_unique(odd_number);
334
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
2 auto actual = GetCapturedStdout();
335 #ifdef __clang__
336 // LLVM compiler performs NRVO
337 EXPECT_THAT(actual, Not(AnyOf(HasSubstr("copy"), HasSubstr("move"))));
338 #else // not __clang__
339 // Other compilers do not
340
6/18
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 14 taken 1 times.
✗ Branch 15 not taken.
✓ Branch 17 taken 1 times.
✗ Branch 18 not taken.
✓ Branch 20 taken 1 times.
✗ Branch 21 not taken.
✗ Branch 31 not taken.
✓ Branch 32 taken 1 times.
✗ Branch 35 not taken.
✗ Branch 36 not taken.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✗ Branch 45 not taken.
✗ Branch 46 not taken.
2 EXPECT_THAT(actual, AnyOf(HasSubstr("copy"), HasSubstr("move")));
341 #endif // __clang__
342
4/14
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 12 taken 1 times.
✗ Branch 13 not taken.
✗ Branch 19 not taken.
✓ Branch 20 taken 1 times.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
2 EXPECT_THAT(v.name(), EndsWith("odd"));
343
3/6
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
2 std::cout << std::endl << actual << std::endl;
344 4 }
345
346 8 TEST(CopyElision, nrvo_parameter) {
347
2/4
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
6 auto p = Verbose<>{"local"};
348
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
2 CaptureStdout();
349
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
2 auto v1 = nrvo_value_parameter(p);
350
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
2 auto actual = GetCapturedStdout();
351
6/18
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 14 taken 1 times.
✗ Branch 15 not taken.
✓ Branch 17 taken 1 times.
✗ Branch 18 not taken.
✓ Branch 20 taken 1 times.
✗ Branch 21 not taken.
✗ Branch 31 not taken.
✓ Branch 32 taken 1 times.
✗ Branch 35 not taken.
✗ Branch 36 not taken.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✗ Branch 45 not taken.
✗ Branch 46 not taken.
2 EXPECT_THAT(actual, AnyOf(HasSubstr("copy"), HasSubstr("move")));
352
3/6
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
2 std::cout << std::endl << actual << std::endl;
353
354
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
2 CaptureStdout();
355
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
2 auto v2 = nrvo_const_ref_parameter(p);
356
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
2 actual = GetCapturedStdout();
357
6/18
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 14 taken 1 times.
✗ Branch 15 not taken.
✓ Branch 17 taken 1 times.
✗ Branch 18 not taken.
✓ Branch 20 taken 1 times.
✗ Branch 21 not taken.
✗ Branch 31 not taken.
✓ Branch 32 taken 1 times.
✗ Branch 35 not taken.
✗ Branch 36 not taken.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✗ Branch 45 not taken.
✗ Branch 46 not taken.
2 EXPECT_THAT(actual, AnyOf(HasSubstr("copy"), HasSubstr("move")));
358
3/6
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
2 std::cout << std::endl << actual << std::endl;
359
360
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
2 CaptureStdout();
361 4 auto v3 = nrvo_move_parameter(std::move(p));
362
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
2 actual = GetCapturedStdout();
363
6/18
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 14 taken 1 times.
✗ Branch 15 not taken.
✓ Branch 17 taken 1 times.
✗ Branch 18 not taken.
✓ Branch 20 taken 1 times.
✗ Branch 21 not taken.
✗ Branch 31 not taken.
✓ Branch 32 taken 1 times.
✗ Branch 35 not taken.
✗ Branch 36 not taken.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✗ Branch 45 not taken.
✗ Branch 46 not taken.
2 EXPECT_THAT(actual, AnyOf(HasSubstr("copy"), HasSubstr("move")));
364
3/6
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
2 std::cout << std::endl << actual << std::endl;
365 4 }
366
367 #if __cplusplus >= 201703L // since C++17
368
369 8 TEST(CopyElision, output_parameter) {
370
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
6 auto name = std::string{"local"};
371
2/4
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
2 auto p1 = Verbose<Uncopyable>{name};
372
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
2 CaptureStdout();
373
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
2 rvo_output_parameter(p1);
374
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
2 auto actual = GetCapturedStdout();
375
5/16
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 1 times.
✗ Branch 12 not taken.
✓ Branch 17 taken 1 times.
✗ Branch 18 not taken.
✗ Branch 26 not taken.
✓ Branch 27 taken 1 times.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
✗ Branch 36 not taken.
✗ Branch 37 not taken.
✗ Branch 40 not taken.
✗ Branch 41 not taken.
2 EXPECT_THAT(p1.name(), Not(StrEq(name)));
376
6/18
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 14 taken 1 times.
✗ Branch 15 not taken.
✓ Branch 17 taken 1 times.
✗ Branch 18 not taken.
✓ Branch 20 taken 1 times.
✗ Branch 21 not taken.
✗ Branch 31 not taken.
✓ Branch 32 taken 1 times.
✗ Branch 35 not taken.
✗ Branch 36 not taken.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✗ Branch 45 not taken.
✗ Branch 46 not taken.
2 EXPECT_THAT(actual, AnyOf(HasSubstr("copy"), HasSubstr("move")));
377
3/6
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
2 std::cout << std::endl << actual << std::endl;
378
379
2/4
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
2 auto p2 = Verbose<Unmovable>{name};
380
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
2 CaptureStdout();
381
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
2 nrvo_output_parameter(p2);
382
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
2 actual = GetCapturedStdout();
383
5/16
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 1 times.
✗ Branch 12 not taken.
✓ Branch 17 taken 1 times.
✗ Branch 18 not taken.
✗ Branch 26 not taken.
✓ Branch 27 taken 1 times.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
✗ Branch 36 not taken.
✗ Branch 37 not taken.
✗ Branch 40 not taken.
✗ Branch 41 not taken.
2 EXPECT_THAT(p2.name(), Not(StrEq(name)));
384
6/18
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 14 taken 1 times.
✗ Branch 15 not taken.
✓ Branch 17 taken 1 times.
✗ Branch 18 not taken.
✓ Branch 20 taken 1 times.
✗ Branch 21 not taken.
✗ Branch 31 not taken.
✓ Branch 32 taken 1 times.
✗ Branch 35 not taken.
✗ Branch 36 not taken.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✗ Branch 45 not taken.
✗ Branch 46 not taken.
2 EXPECT_THAT(actual, AnyOf(HasSubstr("copy"), HasSubstr("move")));
385
3/6
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
2 std::cout << std::endl << actual << std::endl;
386 4 }
387
388 #endif // C++17
389
390 #if __cplusplus >= 201402L // since C++14
391
392 8 TEST(CopyElision, rvo_tuple_get) {
393 // Good: use get to access tuple elements by reference
394 // without copying or moving.
395
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
2 CaptureStdout();
396
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
2 auto result = rvo_tuple();
397 2 auto& v1 = std::get<0>(result);
398 2 auto& v2 = std::get<1>(result);
399
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
2 auto actual = GetCapturedStdout();
400
4/14
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
✗ Branch 20 not taken.
✓ Branch 21 taken 1 times.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
2 EXPECT_THAT(v1.name(), StrEq("first"));
401
4/14
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
✗ Branch 20 not taken.
✓ Branch 21 taken 1 times.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
2 EXPECT_THAT(v2.name(), StrEq("second"));
402
7/20
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 11 taken 1 times.
✗ Branch 12 not taken.
✓ Branch 15 taken 1 times.
✗ Branch 16 not taken.
✓ Branch 18 taken 1 times.
✗ Branch 19 not taken.
✓ Branch 21 taken 1 times.
✗ Branch 22 not taken.
✓ Branch 24 taken 1 times.
✗ Branch 25 not taken.
✗ Branch 37 not taken.
✓ Branch 38 taken 1 times.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✗ Branch 47 not taken.
✗ Branch 48 not taken.
✗ Branch 51 not taken.
✗ Branch 52 not taken.
2 EXPECT_THAT(actual, Not(AnyOf(HasSubstr("copy"), HasSubstr("move"))));
403
3/6
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
2 std::cout << std::endl << actual << std::endl;
404 4 }
405
406 #endif // C++14
407
408 #if __cplusplus >= 201703L // since C++17
409
410 8 TEST(CopyElision, rvo_tuple_structured_binding) {
411 // Better: use structured binding to access tuple elements.
412 // Same efficiency, less verbose.
413
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
2 CaptureStdout();
414
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
6 auto [v1, v2] = rvo_tuple();
415
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
2 auto actual = GetCapturedStdout();
416
4/14
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
✗ Branch 20 not taken.
✓ Branch 21 taken 1 times.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
2 EXPECT_THAT(v1.name(), StrEq("first"));
417
4/14
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
✗ Branch 20 not taken.
✓ Branch 21 taken 1 times.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
2 EXPECT_THAT(v2.name(), StrEq("second"));
418
7/20
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 11 taken 1 times.
✗ Branch 12 not taken.
✓ Branch 15 taken 1 times.
✗ Branch 16 not taken.
✓ Branch 18 taken 1 times.
✗ Branch 19 not taken.
✓ Branch 21 taken 1 times.
✗ Branch 22 not taken.
✓ Branch 24 taken 1 times.
✗ Branch 25 not taken.
✗ Branch 37 not taken.
✓ Branch 38 taken 1 times.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✗ Branch 47 not taken.
✗ Branch 48 not taken.
✗ Branch 51 not taken.
✗ Branch 52 not taken.
2 EXPECT_THAT(actual, Not(AnyOf(HasSubstr("copy"), HasSubstr("move"))));
419
3/6
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
2 std::cout << std::endl << actual << std::endl;
420
1/4
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
6 }
421
422 #endif // C++17
423
424 #if __cplusplus >= 201402L // since C++14
425
426 8 TEST(CopyElision, rvo_tuple_tie) {
427 // Bad: use tie to access tuple elements.
428 // Constructor invoked for each local variable.
429 // Assignment operator invoked for each local variable.
430
2/4
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
6 auto v1 = Verbose<>{"one"};
431
2/4
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
6 auto v2 = Verbose<>{"two"};
432
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
2 CaptureStdout();
433
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
2 std::tie(v1, v2) = rvo_tuple();
434
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
2 auto actual = GetCapturedStdout();
435
4/14
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 12 taken 1 times.
✗ Branch 13 not taken.
✗ Branch 19 not taken.
✓ Branch 20 taken 1 times.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
2 EXPECT_THAT(v1.name(), EndsWith("first"));
436
4/14
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 12 taken 1 times.
✗ Branch 13 not taken.
✗ Branch 19 not taken.
✓ Branch 20 taken 1 times.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
2 EXPECT_THAT(v2.name(), EndsWith("second"));
437
7/20
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 11 taken 1 times.
✗ Branch 12 not taken.
✓ Branch 15 taken 1 times.
✗ Branch 16 not taken.
✓ Branch 18 taken 1 times.
✗ Branch 19 not taken.
✓ Branch 21 taken 1 times.
✗ Branch 22 not taken.
✓ Branch 24 taken 1 times.
✗ Branch 25 not taken.
✗ Branch 37 not taken.
✓ Branch 38 taken 1 times.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✗ Branch 47 not taken.
✗ Branch 48 not taken.
✗ Branch 51 not taken.
✗ Branch 52 not taken.
2 EXPECT_THAT(
438 actual,
439 Not(
440 AnyOf(HasSubstr("copy constructor"),
441 2 HasSubstr("move constructor"))));
442
4/14
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✗ Branch 17 not taken.
✓ Branch 18 taken 1 times.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✗ Branch 31 not taken.
✗ Branch 32 not taken.
2 EXPECT_THAT(actual, HasSubstr("assignment"));
443
3/6
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
2 std::cout << std::endl << actual << std::endl;
444 4 }
445
446 8 TEST(CopyElision, nrvo_tuple_get) {
447 // Good: use get to access tuple elements by reference
448 // without copying or moving.
449
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
2 CaptureStdout();
450
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
2 auto result = nrvo_tuple_good();
451 2 auto& v1 = std::get<0>(result);
452 2 auto& v2 = std::get<1>(result);
453
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
2 auto actual = GetCapturedStdout();
454
4/14
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
✗ Branch 20 not taken.
✓ Branch 21 taken 1 times.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
2 EXPECT_THAT(v1.name(), StrEq("first"));
455
4/14
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
✗ Branch 20 not taken.
✓ Branch 21 taken 1 times.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
2 EXPECT_THAT(v2.name(), StrEq("second"));
456
7/20
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 11 taken 1 times.
✗ Branch 12 not taken.
✓ Branch 15 taken 1 times.
✗ Branch 16 not taken.
✓ Branch 18 taken 1 times.
✗ Branch 19 not taken.
✓ Branch 21 taken 1 times.
✗ Branch 22 not taken.
✓ Branch 24 taken 1 times.
✗ Branch 25 not taken.
✗ Branch 37 not taken.
✓ Branch 38 taken 1 times.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✗ Branch 47 not taken.
✗ Branch 48 not taken.
✗ Branch 51 not taken.
✗ Branch 52 not taken.
2 EXPECT_THAT(actual, Not(AnyOf(HasSubstr("copy"), HasSubstr("move"))));
457
3/6
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
2 std::cout << std::endl << actual << std::endl;
458 4 }
459
460 #include "compat/lang17.hpp"
461
462 8 TEST(CopyElision, nrvo_tuple_macro) {
463 // Good-ish: use macro to access tuple elements without copying or moving.
464
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
2 CaptureStdout();
465
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
2 auto result = nrvo_tuple_good();
466 2 STRUCTURED_BINDING_2(v1, v2, result);
467
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
2 auto actual = GetCapturedStdout();
468
4/14
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
✗ Branch 20 not taken.
✓ Branch 21 taken 1 times.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
2 EXPECT_THAT(v1.name(), StrEq("first"));
469
4/14
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
✗ Branch 20 not taken.
✓ Branch 21 taken 1 times.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
2 EXPECT_THAT(v2.name(), StrEq("second"));
470
7/20
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 11 taken 1 times.
✗ Branch 12 not taken.
✓ Branch 15 taken 1 times.
✗ Branch 16 not taken.
✓ Branch 18 taken 1 times.
✗ Branch 19 not taken.
✓ Branch 21 taken 1 times.
✗ Branch 22 not taken.
✓ Branch 24 taken 1 times.
✗ Branch 25 not taken.
✗ Branch 37 not taken.
✓ Branch 38 taken 1 times.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✗ Branch 47 not taken.
✗ Branch 48 not taken.
✗ Branch 51 not taken.
✗ Branch 52 not taken.
2 EXPECT_THAT(actual, Not(AnyOf(HasSubstr("copy"), HasSubstr("move"))));
471
3/6
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
2 std::cout << std::endl << actual << std::endl;
472 4 }
473
474 #endif // C++14
475
476 #if __cplusplus >= 201703L // since C++17
477
478 8 TEST(CopyElision, nrvo_tuple_structured_binding) {
479 // Better: use structured binding to access tuple elements.
480 // Same efficiency, less verbose.
481
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
2 CaptureStdout();
482
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
6 auto [v1, v2] = nrvo_tuple_better();
483
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
2 auto actual = GetCapturedStdout();
484
4/14
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
✗ Branch 20 not taken.
✓ Branch 21 taken 1 times.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
2 EXPECT_THAT(v1.name(), StrEq("first"));
485
4/14
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
✗ Branch 20 not taken.
✓ Branch 21 taken 1 times.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
2 EXPECT_THAT(v2.name(), StrEq("second"));
486
7/20
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 11 taken 1 times.
✗ Branch 12 not taken.
✓ Branch 15 taken 1 times.
✗ Branch 16 not taken.
✓ Branch 18 taken 1 times.
✗ Branch 19 not taken.
✓ Branch 21 taken 1 times.
✗ Branch 22 not taken.
✓ Branch 24 taken 1 times.
✗ Branch 25 not taken.
✗ Branch 37 not taken.
✓ Branch 38 taken 1 times.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✗ Branch 47 not taken.
✗ Branch 48 not taken.
✗ Branch 51 not taken.
✗ Branch 52 not taken.
2 EXPECT_THAT(actual, Not(AnyOf(HasSubstr("copy"), HasSubstr("move"))));
487
3/6
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
2 std::cout << std::endl << actual << std::endl;
488
1/4
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
6 }
489
490 8 TEST(CopyElision, nrvo_tuple_tie) {
491 // Bad: use tie to access tuple elements.
492 // Local variables must be constructed before call.
493 // Results are assigned to local variables.
494
2/4
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
6 auto v1 = Verbose{"one"};
495
2/4
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
6 auto v2 = Verbose{"two"};
496
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
2 CaptureStdout();
497
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
2 std::tie(v1, v2) = nrvo_tuple_better();
498
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
2 auto actual = GetCapturedStdout();
499
4/14
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 12 taken 1 times.
✗ Branch 13 not taken.
✗ Branch 19 not taken.
✓ Branch 20 taken 1 times.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
2 EXPECT_THAT(v1.name(), EndsWith("first"));
500
4/14
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 12 taken 1 times.
✗ Branch 13 not taken.
✗ Branch 19 not taken.
✓ Branch 20 taken 1 times.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
2 EXPECT_THAT(v2.name(), EndsWith("second"));
501
7/20
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 11 taken 1 times.
✗ Branch 12 not taken.
✓ Branch 15 taken 1 times.
✗ Branch 16 not taken.
✓ Branch 18 taken 1 times.
✗ Branch 19 not taken.
✓ Branch 21 taken 1 times.
✗ Branch 22 not taken.
✓ Branch 24 taken 1 times.
✗ Branch 25 not taken.
✗ Branch 37 not taken.
✓ Branch 38 taken 1 times.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✗ Branch 47 not taken.
✗ Branch 48 not taken.
✗ Branch 51 not taken.
✗ Branch 52 not taken.
2 EXPECT_THAT(
502 actual,
503 Not(
504 AnyOf(HasSubstr("copy constructor"),
505 2 HasSubstr("move constructor"))));
506
4/14
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✗ Branch 17 not taken.
✓ Branch 18 taken 1 times.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✗ Branch 31 not taken.
✗ Branch 32 not taken.
2 EXPECT_THAT(actual, HasSubstr("assignment"));
507
3/6
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
2 std::cout << std::endl << actual << std::endl;
508 4 }
509
510 #endif // C++17
511
512 #if __cplusplus >= 201402L // since C++14
513
514 8 TEST(CopyElision, nrvo_struct) {
515
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
2 CaptureStdout();
516
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
2 auto result = nrvo_struct();
517
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
2 auto actual = GetCapturedStdout();
518
4/14
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 12 taken 1 times.
✗ Branch 13 not taken.
✗ Branch 19 not taken.
✓ Branch 20 taken 1 times.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
2 EXPECT_THAT(result.first.name(), EndsWith("first"));
519
4/14
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 12 taken 1 times.
✗ Branch 13 not taken.
✗ Branch 19 not taken.
✓ Branch 20 taken 1 times.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
2 EXPECT_THAT(result.second.name(), EndsWith("second"));
520
7/20
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 11 taken 1 times.
✗ Branch 12 not taken.
✓ Branch 15 taken 1 times.
✗ Branch 16 not taken.
✓ Branch 18 taken 1 times.
✗ Branch 19 not taken.
✓ Branch 21 taken 1 times.
✗ Branch 22 not taken.
✓ Branch 24 taken 1 times.
✗ Branch 25 not taken.
✗ Branch 37 not taken.
✓ Branch 38 taken 1 times.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✗ Branch 47 not taken.
✗ Branch 48 not taken.
✗ Branch 51 not taken.
✗ Branch 52 not taken.
2 EXPECT_THAT(actual, Not(AnyOf(HasSubstr("copy"), HasSubstr("move"))));
521
3/6
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
2 std::cout << std::endl << actual << std::endl;
522 4 }
523
524 #endif // C++14
525
526 #if __cplusplus >= 201703L // since C++17
527
528 8 TEST(CopyElision, nrvo_struct_structured_binding) {
529
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
2 CaptureStdout();
530
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
2 auto [v1, v2] = nrvo_struct();
531
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
2 auto actual = GetCapturedStdout();
532
4/14
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 12 taken 1 times.
✗ Branch 13 not taken.
✗ Branch 19 not taken.
✓ Branch 20 taken 1 times.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
2 EXPECT_THAT(v1.name(), StrEq("first"));
533
4/14
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 12 taken 1 times.
✗ Branch 13 not taken.
✗ Branch 19 not taken.
✓ Branch 20 taken 1 times.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
2 EXPECT_THAT(v2.name(), StrEq("second"));
534
7/20
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 11 taken 1 times.
✗ Branch 12 not taken.
✓ Branch 15 taken 1 times.
✗ Branch 16 not taken.
✓ Branch 18 taken 1 times.
✗ Branch 19 not taken.
✓ Branch 21 taken 1 times.
✗ Branch 22 not taken.
✓ Branch 24 taken 1 times.
✗ Branch 25 not taken.
✗ Branch 37 not taken.
✓ Branch 38 taken 1 times.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✗ Branch 47 not taken.
✗ Branch 48 not taken.
✗ Branch 51 not taken.
✗ Branch 52 not taken.
2 EXPECT_THAT(actual, Not(AnyOf(HasSubstr("copy"), HasSubstr("move"))));
535
3/6
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
2 std::cout << std::endl << actual << std::endl;
536 4 }
537
538 #endif // C++17
539
540 8 TEST(CopyElision, initialization) {
541
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
2 CaptureStdout();
542
2/4
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
6 auto v1 = Verbose<>{"one"};
543
2/4
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
6 auto v2 = Verbose<>{"two"};
544
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
2 auto actual = GetCapturedStdout();
545
7/20
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 11 taken 1 times.
✗ Branch 12 not taken.
✓ Branch 15 taken 1 times.
✗ Branch 16 not taken.
✓ Branch 18 taken 1 times.
✗ Branch 19 not taken.
✓ Branch 21 taken 1 times.
✗ Branch 22 not taken.
✓ Branch 24 taken 1 times.
✗ Branch 25 not taken.
✗ Branch 37 not taken.
✓ Branch 38 taken 1 times.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✗ Branch 47 not taken.
✗ Branch 48 not taken.
✗ Branch 51 not taken.
✗ Branch 52 not taken.
2 EXPECT_THAT(actual, Not(AnyOf(HasSubstr("copy"), HasSubstr("move"))));
546
3/6
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
2 std::cout << std::endl << actual << std::endl;
547 4 }
548
549 8 TEST(CopyElision, implicit_conversion) {
550
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
2 CaptureStdout();
551
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
2 auto v = implicit_conversion();
552
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
2 auto actual = GetCapturedStdout();
553
7/20
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 11 taken 1 times.
✗ Branch 12 not taken.
✓ Branch 15 taken 1 times.
✗ Branch 16 not taken.
✓ Branch 18 taken 1 times.
✗ Branch 19 not taken.
✓ Branch 21 taken 1 times.
✗ Branch 22 not taken.
✓ Branch 24 taken 1 times.
✗ Branch 25 not taken.
✗ Branch 37 not taken.
✓ Branch 38 taken 1 times.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✗ Branch 47 not taken.
✗ Branch 48 not taken.
✗ Branch 51 not taken.
✗ Branch 52 not taken.
2 EXPECT_THAT(actual, Not(AnyOf(HasSubstr("copy"), HasSubstr("move"))));
554
4/14
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 12 taken 1 times.
✗ Branch 13 not taken.
✗ Branch 19 not taken.
✓ Branch 20 taken 1 times.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
2 EXPECT_THAT(v.name(), StrEq("Converted to Verbose"));
555
3/6
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
2 std::cout << std::endl << actual << std::endl;
556 4 }
557
558 8 TEST(CopyElision, explicit_conversion) {
559
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
2 CaptureStdout();
560
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
2 auto v = explicit_conversion();
561
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
2 auto actual = GetCapturedStdout();
562
7/20
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 11 taken 1 times.
✗ Branch 12 not taken.
✓ Branch 15 taken 1 times.
✗ Branch 16 not taken.
✓ Branch 18 taken 1 times.
✗ Branch 19 not taken.
✓ Branch 21 taken 1 times.
✗ Branch 22 not taken.
✓ Branch 24 taken 1 times.
✗ Branch 25 not taken.
✗ Branch 37 not taken.
✓ Branch 38 taken 1 times.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✗ Branch 47 not taken.
✗ Branch 48 not taken.
✗ Branch 51 not taken.
✗ Branch 52 not taken.
2 EXPECT_THAT(actual, Not(AnyOf(HasSubstr("copy"), HasSubstr("move"))));
563
4/14
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 12 taken 1 times.
✗ Branch 13 not taken.
✗ Branch 19 not taken.
✓ Branch 20 taken 1 times.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
2 EXPECT_THAT(v.name(), StrEq("Converted to Verbose"));
564
3/6
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
2 std::cout << std::endl << actual << std::endl;
565 4 }
566
567 8 TEST(CopyElision, class_conversion) {
568
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
2 CaptureStdout();
569 2 auto v = class_conversion();
570
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
2 auto actual = GetCapturedStdout();
571
6/18
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 14 taken 1 times.
✗ Branch 15 not taken.
✓ Branch 17 taken 1 times.
✗ Branch 18 not taken.
✓ Branch 20 taken 1 times.
✗ Branch 21 not taken.
✗ Branch 31 not taken.
✓ Branch 32 taken 1 times.
✗ Branch 35 not taken.
✗ Branch 36 not taken.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✗ Branch 45 not taken.
✗ Branch 46 not taken.
2 EXPECT_THAT(actual, AnyOf(HasSubstr("copy"), HasSubstr("move")));
572
5/16
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 1 times.
✗ Branch 12 not taken.
✓ Branch 14 taken 1 times.
✗ Branch 15 not taken.
✗ Branch 23 not taken.
✓ Branch 24 taken 1 times.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
2 EXPECT_THAT(actual, Not(HasSubstr("assignment")));
573
4/14
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 12 taken 1 times.
✗ Branch 13 not taken.
✗ Branch 19 not taken.
✓ Branch 20 taken 1 times.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
2 EXPECT_THAT(v.name(), EndsWith("Derived"));
574
3/6
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
2 std::cout << std::endl << actual << std::endl;
575 4 }
576