mirror of
https://github.com/fish-shell/fish-shell
synced 2024-12-28 22:03:12 +00:00
maybe_t: make maybe_t<T> trivially copyable if T is
When passing a value of type maybe_t<size_t>, clangd complains: Parameter 'cursor' is passed by value and only copied once; consider moving it to avoid unnecessary copies (fix available) We get this warning because maybe_t<size_t> is not trivially copyable because it has a user-defined destructor and copy-constructor. Let's remove them if the contained type is trivially copyable, to avoid such warnings. No functional change.
This commit is contained in:
parent
1ce2961561
commit
9d303a74e3
1 changed files with 36 additions and 16 deletions
52
src/maybe.h
52
src/maybe.h
|
@ -7,10 +7,11 @@
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
namespace maybe_detail {
|
namespace maybe_detail {
|
||||||
// Template magic to make maybe_t<T> copyable iff T is copyable.
|
// Template magic to make maybe_t<T> (trivially) copyable iff T is.
|
||||||
// maybe_impl_t is the "too aggressive" implementation: it is always copyable.
|
|
||||||
|
// This is an unsafe implementation: it is always trivially copyable.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct maybe_impl_t {
|
struct maybe_impl_trivially_copyable_t {
|
||||||
alignas(T) char storage[sizeof(T)];
|
alignas(T) char storage[sizeof(T)];
|
||||||
bool filled = false;
|
bool filled = false;
|
||||||
|
|
||||||
|
@ -38,11 +39,13 @@ struct maybe_impl_t {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
maybe_impl_t() = default;
|
maybe_impl_trivially_copyable_t() = default;
|
||||||
|
|
||||||
// Move construction/assignment from a T.
|
// Move construction/assignment from a T.
|
||||||
explicit maybe_impl_t(T &&v) : filled(true) { new (storage) T(std::forward<T>(v)); }
|
explicit maybe_impl_trivially_copyable_t(T &&v) : filled(true) {
|
||||||
maybe_impl_t &operator=(T &&v) {
|
new (storage) T(std::forward<T>(v));
|
||||||
|
}
|
||||||
|
maybe_impl_trivially_copyable_t &operator=(T &&v) {
|
||||||
if (filled) {
|
if (filled) {
|
||||||
value() = std::move(v);
|
value() = std::move(v);
|
||||||
} else {
|
} else {
|
||||||
|
@ -53,8 +56,8 @@ struct maybe_impl_t {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy construction/assignment from a T.
|
// Copy construction/assignment from a T.
|
||||||
explicit maybe_impl_t(const T &v) : filled(true) { new (storage) T(v); }
|
explicit maybe_impl_trivially_copyable_t(const T &v) : filled(true) { new (storage) T(v); }
|
||||||
maybe_impl_t &operator=(const T &v) {
|
maybe_impl_trivially_copyable_t &operator=(const T &v) {
|
||||||
if (filled) {
|
if (filled) {
|
||||||
value() = v;
|
value() = v;
|
||||||
} else {
|
} else {
|
||||||
|
@ -63,14 +66,26 @@ struct maybe_impl_t {
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Move construction/assignment from a maybe_impl.
|
// This is an unsafe implementation: it is always copyable.
|
||||||
maybe_impl_t(maybe_impl_t &&v) : filled(v.filled) {
|
template <typename T>
|
||||||
|
struct maybe_impl_not_trivially_copyable_t : public maybe_impl_trivially_copyable_t<T> {
|
||||||
|
using base_t = maybe_impl_trivially_copyable_t<T>;
|
||||||
|
using base_t::maybe_impl_trivially_copyable_t;
|
||||||
|
using base_t::operator=;
|
||||||
|
using base_t::filled;
|
||||||
|
using base_t::reset;
|
||||||
|
using base_t::storage;
|
||||||
|
|
||||||
|
// Move construction/assignment from another instance.
|
||||||
|
maybe_impl_not_trivially_copyable_t(maybe_impl_not_trivially_copyable_t &&v) {
|
||||||
|
filled = v.filled;
|
||||||
if (filled) {
|
if (filled) {
|
||||||
new (storage) T(std::move(v.value()));
|
new (storage) T(std::move(v.value()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
maybe_impl_t &operator=(maybe_impl_t &&v) {
|
maybe_impl_not_trivially_copyable_t &operator=(maybe_impl_not_trivially_copyable_t &&v) {
|
||||||
if (!v.filled) {
|
if (!v.filled) {
|
||||||
reset();
|
reset();
|
||||||
} else {
|
} else {
|
||||||
|
@ -79,13 +94,14 @@ struct maybe_impl_t {
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy construction/assignment from a maybe_impl.
|
// Copy construction/assignment from another instance.
|
||||||
maybe_impl_t(const maybe_impl_t &v) : filled(v.filled) {
|
maybe_impl_not_trivially_copyable_t(const maybe_impl_not_trivially_copyable_t &v) : base_t() {
|
||||||
|
filled = v.filled;
|
||||||
if (v.filled) {
|
if (v.filled) {
|
||||||
new (storage) T(v.value());
|
new (storage) T(v.value());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
maybe_impl_t &operator=(const maybe_impl_t &v) {
|
maybe_impl_not_trivially_copyable_t &operator=(const maybe_impl_not_trivially_copyable_t &v) {
|
||||||
if (&v == this) return *this;
|
if (&v == this) return *this;
|
||||||
if (!v.filled) {
|
if (!v.filled) {
|
||||||
reset();
|
reset();
|
||||||
|
@ -95,7 +111,7 @@ struct maybe_impl_t {
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
~maybe_impl_t() { reset(); }
|
~maybe_impl_not_trivially_copyable_t() { reset(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct copyable_t {};
|
struct copyable_t {};
|
||||||
|
@ -128,7 +144,11 @@ inline constexpr none_t none() { return none_t::none; }
|
||||||
// This is a value-type class that stores a value of T in aligned storage.
|
// This is a value-type class that stores a value of T in aligned storage.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class maybe_t : private maybe_detail::conditionally_copyable_t<T> {
|
class maybe_t : private maybe_detail::conditionally_copyable_t<T> {
|
||||||
maybe_detail::maybe_impl_t<T> impl_;
|
using maybe_impl_t =
|
||||||
|
typename std::conditional<std::is_trivially_copyable<T>::value,
|
||||||
|
maybe_detail::maybe_impl_trivially_copyable_t<T>,
|
||||||
|
maybe_detail::maybe_impl_not_trivially_copyable_t<T>>::type;
|
||||||
|
maybe_impl_t impl_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// return whether the receiver contains a value.
|
// return whether the receiver contains a value.
|
||||||
|
|
Loading…
Reference in a new issue