Trivial destructor

This commit is contained in:
Simon Brand
2017-10-01 21:19:46 +01:00
parent 858c558925
commit ed53e55ee7

View File

@@ -61,14 +61,14 @@ namespace tl {
namespace detail { namespace detail {
template <class T, class U> template <class T, class U>
using enable_forward_value = tl::enable_if_t< using enable_forward_value = enable_if_t<
std::is_constructible<T, U&&>::value && std::is_constructible<T, U&&>::value &&
!std::is_same<tl::decay_t<U>, in_place_t>::value && !std::is_same<tl::decay_t<U>, in_place_t>::value &&
!std::is_same<optional<T>, tl::decay_t<U>>::value !std::is_same<optional<T>, tl::decay_t<U>>::value
>; >;
template <class T, class U, class Other> template <class T, class U, class Other>
using enable_from_other = tl::enable_if_t< using enable_from_other = enable_if_t<
std::is_constructible<T, Other>::value && std::is_constructible<T, Other>::value &&
!std::is_constructible<T, optional<U>&>::value && !std::is_constructible<T, optional<U>&>::value &&
!std::is_constructible<T, optional<U>&&>::value && !std::is_constructible<T, optional<U>&&>::value &&
@@ -81,30 +81,30 @@ namespace tl {
>; >;
template <class T, class U> template <class T, class U>
using enable_assign_forward = tl::enable_if_t< using enable_assign_forward = enable_if_t<
!is_same_v<optional<T>, tl::decay_t<U>>::value && !std::is_same<optional<T>, tl::decay_t<U>>::value &&
!tl::conjunction<std::is_scalar<T>, std::is_same<T, tl::decay_t<U>>>::value && !tl::conjunction<std::is_scalar<T>, std::is_same<T, tl::decay_t<U>>>::value &&
std::is_constructible<T, U>::value && std::is_constructible<T, U>::value &&
is_assignable<T&, U>::value std::is_assignable<T&, U>::value
>; >;
template <class T, class U, class Other> template <class T, class U, class Other>
using enable_assign_from_other = tl::enable_if_t< using enable_assign_from_other = enable_if_t<
std::is_constructible<T, Other> && std::is_constructible<T, Other>::value &&
std::is_assignablev<T&, Other> && std::is_assignable<T&, Other>::value &&
!std::is_constructiblev<T, optional<U>&> && !std::is_constructible<T, optional<U>&>::value &&
!std::is_constructiblev<T, optional<U>&&> && !std::is_constructible<T, optional<U>&&>::value &&
!std::is_constructiblev<T, const optional<U>&> && !std::is_constructible<T, const optional<U>&>::value &&
!std::is_constructiblev<T, const optional<U>&&> && !std::is_constructible<T, const optional<U>&&>::value &&
!std::is_convertiblev<optional<U>&, T> && !std::is_convertible<optional<U>&, T>::value &&
!std::is_convertiblev<optional<U>&&, T> && !std::is_convertible<optional<U>&&, T>::value &&
!std::is_convertiblev<const optional<U>&, T> && !std::is_convertible<const optional<U>&, T>::value &&
!std::is_convertiblev<const optional<U>&&, T> && !std::is_convertible<const optional<U>&&, T>::value &&
!std::is_assignablev<T&, optional<U>&> && !std::is_assignable<T&, optional<U>&>::value &&
!std::is_assignablev<T&, optional<U>&&> && !std::is_assignable<T&, optional<U>&&>::value &&
!std::is_assignablev<T&, const optional<U>&> && !std::is_assignable<T&, const optional<U>&>::value &&
!std::is_assignablev<T&, const optional<U>&&> !std::is_assignable<T&, const optional<U>&&>::value
> >;
//TODO improve //TODO improve
template <class T, class=void> template <class T, class=void>
@@ -121,6 +121,7 @@ namespace tl {
template <class T> template <class T>
struct is_nothrow_swappable<T,void_t<decltype(swap(std::declval<T>(), std::declval<T>()))>> struct is_nothrow_swappable<T,void_t<decltype(swap(std::declval<T>(), std::declval<T>()))>>
: std::true_type{}; : std::true_type{};
}
// [optional.nullopt], no-value state indicator // [optional.nullopt], no-value state indicator
struct nullopt_t{ struct nullopt_t{
@@ -272,8 +273,8 @@ template <class T, class U> inline constexpr bool operator>=(const U& lhs, const
// [optional.specalg], specialized algorithms // [optional.specalg], specialized algorithms
template <class T, tl::enable_if_t<std::is_move_constructible<T>::value>* = nullptr, template <class T, enable_if_t<std::is_move_constructible<T>::value>* = nullptr,
tl::enable_if_t<is_swappable<T>::value>* = nullptr> enable_if_t<detail::is_swappable<T>::value>* = nullptr>
void swap(optional<T>& lhs, optional<T>& rhs) noexcept(noexcept(lhs.swap(rhs))) { void swap(optional<T>& lhs, optional<T>& rhs) noexcept(noexcept(lhs.swap(rhs))) {
return lhs.swap(rhs); return lhs.swap(rhs);
} }
@@ -297,7 +298,7 @@ namespace std {
//TODO SFINAE //TODO SFINAE
template <class T> template <class T>
struct hash<tl::optional<T>> { struct hash<tl::optional<T>> {
std::size_t operator() (const tl::optional<T>& o) const { ::std::size_t operator() (const tl::optional<T>& o) const {
if (!o.has_value()) if (!o.has_value())
return 0; return 0;
@@ -307,9 +308,8 @@ namespace std {
} }
namespace tl { namespace tl {
namespace detail { namespace detail {
template <class T, bool = std::is_trivially_destructible<T>::value> template <class T, bool = ::std::is_trivially_destructible<T>::value>
struct optional_storage_base { struct optional_storage_base {
constexpr optional_storage_base() noexcept constexpr optional_storage_base() noexcept
: m_dummy(), m_has_value(false) {} : m_dummy(), m_has_value(false) {}
@@ -333,12 +333,7 @@ namespace tl {
struct optional_storage_base<T, true> { struct optional_storage_base<T, true> {
constexpr optional_storage_base() noexcept constexpr optional_storage_base() noexcept
: m_dummy(), m_has_value(false) {} : m_dummy(), m_has_value(false) {}
~optional_storage_base() { ~optional_storage_base() = default;
if (m_has_value) {
//don't destruct value
m_has_value = false;
}
}
struct dummy{}; struct dummy{};
union { union {
@@ -364,7 +359,7 @@ class optional : private detail::optional_storage_base<T> {
new (std::addressof(this->m_value)) T (rhs.value()); new (std::addressof(this->m_value)) T (rhs.value());
} }
} }
template <class U = T, tl::enable_if_t<std::is_move_constructible<T>::value>* = nullptr> template <class U = T, enable_if_t<std::is_move_constructible<T>::value>* = nullptr>
constexpr optional(optional&& rhs) { constexpr optional(optional&& rhs) {
if (rhs.has_value()) { if (rhs.has_value()) {
this->m_has_value = true; this->m_has_value = true;
@@ -372,27 +367,27 @@ class optional : private detail::optional_storage_base<T> {
} }
} }
template <class... Args> template <class... Args>
constexpr explicit optional(tl::enable_if_t<std::is_constructible<T, Args...>::value, in_place_t>, constexpr explicit optional(enable_if_t<std::is_constructible<T, Args...>::value, in_place_t>,
Args&&... args) { Args&&... args) {
this->m_has_value = true; this->m_has_value = true;
new (std::addressof(this->m_value)) T (std::forward<Args>(args)...); new (std::addressof(this->m_value)) T (std::forward<Args>(args)...);
} }
template <class U, class... Args> template <class U, class... Args>
constexpr explicit optional( constexpr explicit optional(
tl::enable_if_t<std::is_constructible<T, std::initializer_list<U>&, Args&&...>::value, in_place_t>, enable_if_t<std::is_constructible<T, std::initializer_list<U>&, Args&&...>::value, in_place_t>,
std::initializer_list<U> il, Args&&... args) { std::initializer_list<U> il, Args&&... args) {
this->m_has_value = true; this->m_has_value = true;
new (std::addressof(this->m_value)) T (il, std::forward<Args>(args)...); new (std::addressof(this->m_value)) T (il, std::forward<Args>(args)...);
} }
template <class U = T, tl::enable_if_t<std::is_convertible<U&&, T>::value>* = nullptr, template <class U = T, enable_if_t<std::is_convertible<U&&, T>::value>* = nullptr,
detail::enable_forward_value<T,U>* = nullptr> detail::enable_forward_value<T,U>* = nullptr>
constexpr optional(U&& u) { constexpr optional(U&& u) {
this->m_has_value = true; this->m_has_value = true;
new (std::addressof(this->m_value)) T (std::forward<U>(u)); new (std::addressof(this->m_value)) T (std::forward<U>(u));
} }
template <class U = T, tl::enable_if_t<!std::is_convertible<U&&, T>::value>* = nullptr, template <class U = T, enable_if_t<!std::is_convertible<U&&, T>::value>* = nullptr,
detail::enable_forward_value<T,U>* = nullptr> detail::enable_forward_value<T,U>* = nullptr>
constexpr explicit optional(U&& u) { constexpr explicit optional(U&& u) {
this->m_has_value = true; this->m_has_value = true;
@@ -400,21 +395,21 @@ class optional : private detail::optional_storage_base<T> {
} }
template <class U, detail::enable_from_other<T,U,const U&>* = nullptr, template <class U, detail::enable_from_other<T,U,const U&>* = nullptr,
tl::enable_if_t<std::is_convertible<const U&, T>::value>* = nullptr> enable_if_t<std::is_convertible<const U&, T>::value>* = nullptr>
optional(const optional<U>& rhs) { optional(const optional<U>& rhs) {
this->m_has_value = true; this->m_has_value = true;
new (std::addressof(this->m_value)) T (rhs.value()); new (std::addressof(this->m_value)) T (rhs.value());
} }
template <class U, detail::enable_from_other<T,U,const U&>* = nullptr, template <class U, detail::enable_from_other<T,U,const U&>* = nullptr,
tl::enable_if_t<!std::is_convertible<const U&, T>::value>* = nullptr> enable_if_t<!std::is_convertible<const U&, T>::value>* = nullptr>
optional(const optional<U>& rhs) { optional(const optional<U>& rhs) {
this->m_has_value = true; this->m_has_value = true;
new (std::addressof(this->m_value)) T (rhs.value()); new (std::addressof(this->m_value)) T (rhs.value());
} }
template <class U, detail::enable_from_other<T,U,U&&>* = nullptr, template <class U, detail::enable_from_other<T,U,U&&>* = nullptr,
tl::enable_if_t<std::is_convertible<U&&, T>::value>* = nullptr> enable_if_t<std::is_convertible<U&&, T>::value>* = nullptr>
optional(optional<U>&& rhs) { optional(optional<U>&& rhs) {
this->m_has_value = true; this->m_has_value = true;
new (std::addressof(this->m_value)) T (std::move(rhs.value())); new (std::addressof(this->m_value)) T (std::move(rhs.value()));
@@ -488,7 +483,7 @@ class optional : private detail::optional_storage_base<T> {
} }
} }
// TODO SFINAE, check exception guarantee // TODO check exception guarantee
template <class U, detail::enable_assign_from_other<T,U,const U&>* = nullptr> template <class U, detail::enable_assign_from_other<T,U,const U&>* = nullptr>
optional& operator=(const optional<U>& rhs) { optional& operator=(const optional<U>& rhs) {
if (has_value()) { if (has_value()) {
@@ -507,7 +502,7 @@ class optional : private detail::optional_storage_base<T> {
} }
} }
// TODO SFINAE, check exception guarantee // TODO check exception guarantee
template <class U, detail::enable_assign_from_other<T,U,U>* = nullptr> template <class U, detail::enable_assign_from_other<T,U,U>* = nullptr>
optional& operator=(optional<U>&& rhs) { optional& operator=(optional<U>&& rhs) {
if (has_value()) { if (has_value()) {
@@ -535,7 +530,7 @@ class optional : private detail::optional_storage_base<T> {
} }
template <class U, class... Args> template <class U, class... Args>
tl::enable_if_t<std::is_constructible<T, std::initializer_list<U>&, Args&&...>::value, T&> enable_if_t<std::is_constructible<T, std::initializer_list<U>&, Args&&...>::value, T&>
emplace(std::initializer_list<U> il, Args&&... args) { emplace(std::initializer_list<U> il, Args&&... args) {
*this = nullopt; *this = nullopt;
new (std::addressof(this->m_value)) T(il, std::forward<Args>(args)...); new (std::addressof(this->m_value)) T(il, std::forward<Args>(args)...);
@@ -543,7 +538,7 @@ class optional : private detail::optional_storage_base<T> {
// [optional.swap], swap // [optional.swap], swap
void swap(optional& rhs) void swap(optional& rhs)
noexcept(std::is_nothrow_move_constructible<T>::value && is_nothrow_swappable<T>::value) noexcept(std::is_nothrow_move_constructible<T>::value && detail::is_nothrow_swappable<T>::value)
{ {
if (has_value()) { if (has_value()) {
if (rhs.has_value()) { if (rhs.has_value()) {