Got a test case working that shows emplace_back and push_back do the same function calls in every instance except for one.

master
Zed A. Shaw 2 weeks ago
parent bba4b2463e
commit b8395c6d9f
  1. 3
      Makefile
  2. 121
      emplace_move/test.cpp

@ -22,8 +22,7 @@ tracy_build:
meson compile -j 10 -C builddir meson compile -j 10 -C builddir
test: build test: build
./builddir/emplace_test.exe ./builddir/emplace_test.exe "[proof]"
./builddir/rvo_test.exe
clean: clean:
meson compile --clean -C builddir meson compile --clean -C builddir

@ -7,34 +7,88 @@
using namespace fmt; 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 // Some heavy object
struct A { 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) { A(int val) : val(val) {
COUNTS.value_constructor++;
std::cout << "called constructor with: " << val << std::endl; std::cout << "called constructor with: " << val << std::endl;
} }
A(A const& other) { A(A const& other) {
COUNTS.copy_constructor++;
std::cout << "calling copy(A const& other): " << val << std::endl;; std::cout << "calling copy(A const& other): " << val << std::endl;;
} }
A(A&& other) { A(A&& other) {
COUNTS.move_constructor++;
std::cout << "calling move(A&& other): " << val << std::endl;; std::cout << "calling move(A&& other): " << val << std::endl;;
} }
A& operator=(A&& other) { A& operator=(A&& other) {
COUNTS.move_assign++;
std::cout << "calling move(A&& other)=: " << val << std::endl;; std::cout << "calling move(A&& other)=: " << val << std::endl;;
return *this; return *this;
} }
A& operator=(A const& other) { A& operator=(A const& other) {
COUNTS.copy_assign++;
std::cout << "calling copy(A const& other)=: " << val << std::endl;; std::cout << "calling copy(A const& other)=: " << val << std::endl;;
return *this; return *this;
} }
~A() = default; ~A() {
COUNTS.destructor++;
int val{}; 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 // 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"; std::cout << "== 4. Push Back: Calling move constructor\n";
test.push_back(A{}); test.push_back(A{});
} }
TEST_CASE("proof you don't need emplace or std::move", "[proof]") { 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();
} }

Loading…
Cancel
Save