Skip to content

Instantly share code, notes, and snippets.

@elbeno
Created September 17, 2017 17:33
Show Gist options
  • Save elbeno/55a51fb52d05956c6d207cf34b2c94fa to your computer and use it in GitHub Desktop.
Save elbeno/55a51fb52d05956c6d207cf34b2c94fa to your computer and use it in GitHub Desktop.
Using std::exchange to implement move construction/assignment
#include <algorithm>
#include <cassert>
#include <iostream>
#include <memory>
#include <utility>
using namespace std;
struct Foo
{
Foo() : p(nullptr), n(0) {}
Foo(int* p_, int n_) : p(p_), n(n_) {}
Foo(Foo&& f)
: p(std::move(f).p)
, n(std::move(f).n)
{
f.p = nullptr;
f.n = 0;
}
Foo& operator=(Foo&& f) {
if (this == &f) return *this;
p = std::move(f).p;
n = std::move(f).n;
f.p = nullptr;
f.n = 0;
return *this;
}
~Foo() { delete p; }
int* p;
int n;
};
void test_foo()
{
int* p = new int[10];
Foo f1(p, 10);
Foo f2(std::move(f1));
assert(f1.p == nullptr);
f1 = std::move(f2);
assert(f2.p == nullptr);
f1 = std::move(f1);
assert(f1.p != nullptr);
cout << "Foo OK\n";
}
template <typename T, typename U = T>
T exchange_ptr_helper(T obj, U&& new_value)
{
T old_value(std::move(obj));
obj = new_value;
return old_value;
}
struct Bar
{
Bar() : p(nullptr), n(0) {}
Bar(int* p_, int n_) : p(p_), n(n_) {}
Bar(Bar&& f)
: p(std::exchange(f.p, nullptr))
, n(std::exchange(f.n, 0))
{}
Bar& operator=(Bar&& f) {
auto ptr = std::unique_ptr<int>(std::exchange(f.p, nullptr));
p = std::exchange(ptr, nullptr).release();
n = std::exchange(f.n, 0);
return *this;
}
~Bar() { delete p; }
int* p;
int n;
};
void test_bar()
{
int* p = new int[10];
Bar b1(p, 10);
Bar b2(std::move(b1));
assert(b1.p == nullptr);
b1 = std::move(b2);
assert(b2.p == nullptr);
b1 = std::move(b1);
assert(b1.p != nullptr);
cout << "Bar OK\n";
}
struct Baz
{
Baz() : p(nullptr), n(0) {}
Baz(int* p_, int n_) : p(p_), n(n_) {}
Baz(Baz&& f)
: p(std::exchange(f.p, nullptr))
, n(std::exchange(f.n, 0))
{}
Baz& operator=(Baz&& f) {
if (this == &f) return *this;
p = std::exchange(f.p, nullptr);
n = std::exchange(f.n, 0);
return *this;
}
~Baz() { delete p; }
int* p;
int n;
};
void test_baz()
{
int* p = new int[10];
Baz b1(p, 10);
Baz b2(std::move(b1));
assert(b1.p == nullptr);
b1 = std::move(b2);
assert(b2.p == nullptr);
b1 = std::move(b1);
assert(b1.p != nullptr);
cout << "Baz OK\n";
}
int main()
{
test_foo();
test_bar();
test_baz();
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment