|
|
|
@ -7,34 +7,88 @@ |
|
|
|
|
|
|
|
|
|
using namespace fmt; |
|
|
|
|
|
|
|
|
|
struct Counts { |
|
|
|
|
int default_constructor = 0; |
|
|
|
|
int value_constructor = 0; |
|
|
|
|
int copy_constructor = 0; |
|
|
|
|
int move_constructor = 0; |
|
|
|
|
int move_assign = 0; |
|
|
|
|
int copy_assign = 0; |
|
|
|
|
int destructor = 0; |
|
|
|
|
|
|
|
|
|
void reset() { |
|
|
|
|
default_constructor = 0; |
|
|
|
|
value_constructor = 0; |
|
|
|
|
copy_constructor = 0; |
|
|
|
|
move_constructor = 0; |
|
|
|
|
move_assign = 0; |
|
|
|
|
copy_assign = 0; |
|
|
|
|
destructor = 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
int totals() { |
|
|
|
|
return default_constructor + |
|
|
|
|
value_constructor + |
|
|
|
|
copy_constructor + |
|
|
|
|
move_constructor + |
|
|
|
|
move_assign + |
|
|
|
|
copy_assign + |
|
|
|
|
destructor; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void dump() { |
|
|
|
|
fmt::println("default_constructor {} value_constructor {} copy_constructor {} move_constructor {} move_assign {} copy_assign", |
|
|
|
|
default_constructor, |
|
|
|
|
value_constructor, |
|
|
|
|
copy_constructor, |
|
|
|
|
move_constructor, |
|
|
|
|
move_assign, |
|
|
|
|
copy_assign, |
|
|
|
|
destructor); |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
Counts COUNTS; |
|
|
|
|
|
|
|
|
|
// Some heavy object
|
|
|
|
|
struct A { |
|
|
|
|
A() = default; |
|
|
|
|
int val = 0; |
|
|
|
|
|
|
|
|
|
A() { |
|
|
|
|
COUNTS.default_constructor++; |
|
|
|
|
std::cout << "default called constructor with: " << val << std::endl; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
A(int val) : val(val) { |
|
|
|
|
COUNTS.value_constructor++; |
|
|
|
|
std::cout << "called constructor with: " << val << std::endl; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
A(A const& other) { |
|
|
|
|
COUNTS.copy_constructor++; |
|
|
|
|
std::cout << "calling copy(A const& other): " << val << std::endl;; |
|
|
|
|
} |
|
|
|
|
A(A&& other) { |
|
|
|
|
COUNTS.move_constructor++; |
|
|
|
|
std::cout << "calling move(A&& other): " << val << std::endl;; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
A& operator=(A&& other) { |
|
|
|
|
COUNTS.move_assign++; |
|
|
|
|
std::cout << "calling move(A&& other)=: " << val << std::endl;; |
|
|
|
|
return *this; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
A& operator=(A const& other) { |
|
|
|
|
COUNTS.copy_assign++; |
|
|
|
|
std::cout << "calling copy(A const& other)=: " << val << std::endl;; |
|
|
|
|
return *this; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
~A() = default; |
|
|
|
|
|
|
|
|
|
int val{}; |
|
|
|
|
~A() { |
|
|
|
|
COUNTS.destructor++; |
|
|
|
|
std::cout << "destructor called" << std::endl; |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -92,9 +146,68 @@ TEST_CASE("pushback move tests", "[push_back]") { |
|
|
|
|
// to put the value in a slot so the compiler had to call the move constructor
|
|
|
|
|
std::cout << "== 4. Push Back: Calling move constructor\n"; |
|
|
|
|
test.push_back(A{}); |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
TEST_CASE("proof you don't need emplace or std::move", "[proof]") { |
|
|
|
|
A a{20}; |
|
|
|
|
A b{30}; |
|
|
|
|
COUNTS.reset(); |
|
|
|
|
|
|
|
|
|
std::vector<A> emtest; |
|
|
|
|
emtest.reserve(10); |
|
|
|
|
|
|
|
|
|
std::vector<A> pbtest; |
|
|
|
|
pbtest.reserve(10); |
|
|
|
|
REQUIRE(COUNTS.totals() == 0); |
|
|
|
|
|
|
|
|
|
emtest.emplace_back(a); |
|
|
|
|
REQUIRE(COUNTS.totals() == 1); |
|
|
|
|
COUNTS.dump(); |
|
|
|
|
COUNTS.reset(); |
|
|
|
|
|
|
|
|
|
pbtest.push_back(b); |
|
|
|
|
REQUIRE(COUNTS.totals() == 1); |
|
|
|
|
COUNTS.dump(); |
|
|
|
|
COUNTS.reset(); |
|
|
|
|
|
|
|
|
|
// confirm these do the same number of calls
|
|
|
|
|
emtest.emplace_back(A{}); |
|
|
|
|
REQUIRE(COUNTS.totals() == 3); |
|
|
|
|
COUNTS.dump(); |
|
|
|
|
COUNTS.reset(); |
|
|
|
|
|
|
|
|
|
pbtest.push_back(A{}); |
|
|
|
|
REQUIRE(COUNTS.totals() == 3); |
|
|
|
|
COUNTS.dump(); |
|
|
|
|
COUNTS.reset(); |
|
|
|
|
|
|
|
|
|
{ |
|
|
|
|
REQUIRE(COUNTS.totals() == 0); |
|
|
|
|
|
|
|
|
|
A c{}; |
|
|
|
|
emtest.emplace_back(std::move(c)); |
|
|
|
|
REQUIRE(COUNTS.totals() == 2); |
|
|
|
|
COUNTS.dump(); |
|
|
|
|
COUNTS.reset(); |
|
|
|
|
|
|
|
|
|
A d{}; |
|
|
|
|
pbtest.push_back(std::move(d)); |
|
|
|
|
REQUIRE(COUNTS.totals() == 2); |
|
|
|
|
COUNTS.dump(); |
|
|
|
|
COUNTS.reset(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
COUNTS.reset(); |
|
|
|
|
|
|
|
|
|
emtest.emplace_back(200); |
|
|
|
|
REQUIRE(COUNTS.totals() == 1); |
|
|
|
|
COUNTS.dump(); |
|
|
|
|
COUNTS.reset(); |
|
|
|
|
|
|
|
|
|
pbtest.push_back(200); |
|
|
|
|
REQUIRE(COUNTS.totals() == 3); |
|
|
|
|
COUNTS.dump(); |
|
|
|
|
COUNTS.reset(); |
|
|
|
|
} |
|
|
|
|