mirror of
https://github.com/privatevoid-net/nix-super.git
synced 2024-11-15 02:36:16 +02:00
refactor(treewide): make some move ctors noexcept where appropriate
This is good practice to avoid pessimisations. Left comments for the reasoning why ctors should be noexcept. There are some tricky cases where we intentionally want throwing move ctors/assignments. But those cases should really be reviewed, since some of those can be replaced with more idiomatic copy/move-and-swap.
This commit is contained in:
parent
492c678162
commit
96eeb6f4ff
8 changed files with 27 additions and 9 deletions
|
@ -141,7 +141,9 @@ public:
|
||||||
Value * * elems;
|
Value * * elems;
|
||||||
ListBuilder(EvalState & state, size_t size);
|
ListBuilder(EvalState & state, size_t size);
|
||||||
|
|
||||||
ListBuilder(ListBuilder && x)
|
// NOTE: Can be noexcept because we are just copying integral values and
|
||||||
|
// raw pointers.
|
||||||
|
ListBuilder(ListBuilder && x) noexcept
|
||||||
: size(x.size)
|
: size(x.size)
|
||||||
, inlineElems{x.inlineElems[0], x.inlineElems[1]}
|
, inlineElems{x.inlineElems[0], x.inlineElems[1]}
|
||||||
, elems(size <= 2 ? inlineElems : x.elems)
|
, elems(size <= 2 ? inlineElems : x.elems)
|
||||||
|
|
|
@ -40,7 +40,7 @@ struct RemoteStore::ConnectionHandle
|
||||||
: handle(std::move(handle))
|
: handle(std::move(handle))
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
ConnectionHandle(ConnectionHandle && h)
|
ConnectionHandle(ConnectionHandle && h) noexcept
|
||||||
: handle(std::move(h.handle))
|
: handle(std::move(h.handle))
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
|
|
|
@ -42,7 +42,8 @@ struct SQLite
|
||||||
SQLite(const Path & path, SQLiteOpenMode mode = SQLiteOpenMode::Normal);
|
SQLite(const Path & path, SQLiteOpenMode mode = SQLiteOpenMode::Normal);
|
||||||
SQLite(const SQLite & from) = delete;
|
SQLite(const SQLite & from) = delete;
|
||||||
SQLite& operator = (const SQLite & from) = delete;
|
SQLite& operator = (const SQLite & from) = delete;
|
||||||
SQLite& operator = (SQLite && from) { db = from.db; from.db = 0; return *this; }
|
// NOTE: This is noexcept since we are only copying and assigning raw pointers.
|
||||||
|
SQLite& operator = (SQLite && from) noexcept { db = from.db; from.db = 0; return *this; }
|
||||||
~SQLite();
|
~SQLite();
|
||||||
operator sqlite3 * () { return db; }
|
operator sqlite3 * () { return db; }
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,9 @@ public:
|
||||||
|
|
||||||
Callback(std::function<void(std::future<T>)> fun) : fun(fun) { }
|
Callback(std::function<void(std::future<T>)> fun) : fun(fun) { }
|
||||||
|
|
||||||
Callback(Callback && callback) : fun(std::move(callback.fun))
|
// NOTE: std::function is noexcept move-constructible since C++20.
|
||||||
|
Callback(Callback && callback) noexcept(std::is_nothrow_move_constructible_v<decltype(fun)>)
|
||||||
|
: fun(std::move(callback.fun))
|
||||||
{
|
{
|
||||||
auto prev = callback.done.test_and_set();
|
auto prev = callback.done.test_and_set();
|
||||||
if (prev) done.test_and_set();
|
if (prev) done.test_and_set();
|
||||||
|
|
|
@ -45,8 +45,9 @@ AutoCloseFD::AutoCloseFD() : fd{INVALID_DESCRIPTOR} {}
|
||||||
|
|
||||||
AutoCloseFD::AutoCloseFD(Descriptor fd) : fd{fd} {}
|
AutoCloseFD::AutoCloseFD(Descriptor fd) : fd{fd} {}
|
||||||
|
|
||||||
|
// NOTE: This can be noexcept since we are just copying a value and resetting
|
||||||
AutoCloseFD::AutoCloseFD(AutoCloseFD && that) : fd{that.fd}
|
// the file descriptor in the rhs.
|
||||||
|
AutoCloseFD::AutoCloseFD(AutoCloseFD && that) noexcept : fd{that.fd}
|
||||||
{
|
{
|
||||||
that.fd = INVALID_DESCRIPTOR;
|
that.fd = INVALID_DESCRIPTOR;
|
||||||
}
|
}
|
||||||
|
|
|
@ -155,7 +155,7 @@ public:
|
||||||
AutoCloseFD();
|
AutoCloseFD();
|
||||||
AutoCloseFD(Descriptor fd);
|
AutoCloseFD(Descriptor fd);
|
||||||
AutoCloseFD(const AutoCloseFD & fd) = delete;
|
AutoCloseFD(const AutoCloseFD & fd) = delete;
|
||||||
AutoCloseFD(AutoCloseFD&& fd);
|
AutoCloseFD(AutoCloseFD&& fd) noexcept;
|
||||||
~AutoCloseFD();
|
~AutoCloseFD();
|
||||||
AutoCloseFD& operator =(const AutoCloseFD & fd) = delete;
|
AutoCloseFD& operator =(const AutoCloseFD & fd) = delete;
|
||||||
AutoCloseFD& operator =(AutoCloseFD&& fd);
|
AutoCloseFD& operator =(AutoCloseFD&& fd);
|
||||||
|
|
|
@ -20,7 +20,11 @@ public:
|
||||||
// Copying Finallys is definitely not a good idea and will cause them to be
|
// Copying Finallys is definitely not a good idea and will cause them to be
|
||||||
// called twice.
|
// called twice.
|
||||||
Finally(Finally &other) = delete;
|
Finally(Finally &other) = delete;
|
||||||
Finally(Finally &&other) : fun(std::move(other.fun)) {
|
// NOTE: Move constructor can be nothrow if the callable type is itself nothrow
|
||||||
|
// move-constructible.
|
||||||
|
Finally(Finally && other) noexcept(std::is_nothrow_move_constructible_v<Fn>)
|
||||||
|
: fun(std::move(other.fun))
|
||||||
|
{
|
||||||
other.movedFrom = true;
|
other.movedFrom = true;
|
||||||
}
|
}
|
||||||
~Finally() noexcept(false)
|
~Finally() noexcept(false)
|
||||||
|
|
|
@ -109,7 +109,15 @@ public:
|
||||||
Handle(Pool & pool, std::shared_ptr<R> r) : pool(pool), r(r) { }
|
Handle(Pool & pool, std::shared_ptr<R> r) : pool(pool), r(r) { }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Handle(Handle && h) : pool(h.pool), r(h.r) { h.r.reset(); }
|
// NOTE: Copying std::shared_ptr and calling a .reset() on it is always noexcept.
|
||||||
|
Handle(Handle && h) noexcept
|
||||||
|
: pool(h.pool)
|
||||||
|
, r(h.r)
|
||||||
|
{
|
||||||
|
static_assert(noexcept(h.r.reset()));
|
||||||
|
static_assert(noexcept(std::shared_ptr(h.r)));
|
||||||
|
h.r.reset();
|
||||||
|
}
|
||||||
|
|
||||||
Handle(const Handle & l) = delete;
|
Handle(const Handle & l) = delete;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue