diff --git a/optional.hpp b/optional.hpp index 9e49464..223709e 100644 --- a/optional.hpp +++ b/optional.hpp @@ -39,6 +39,16 @@ #define TL_OPTIONAL_NO_CONSTRR #endif +#if __GNUG__ && __GNUC__ < 5 +#define IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) std::has_trivial_copy_constructor::value +#define IS_TRIVIALLY_COPY_ASSIGNABLE(T) std::has_trivial_copy_assign::value +#define IS_TRIVIALLY_DESTRUCTIBLE(T) std::is_trivially_destructible::value +#else +#define IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) std::is_trivially_copy_constructible::value +#define IS_TRIVIALLY_COPY_ASSIGNABLE(T) std::is_trivially_copy_assignable::value +#define IS_TRIVIALLY_DESTRUCTIBLE(T) std::is_trivially_destructible::value +#endif + #if __cplusplus > 201103L #define TL_OPTIONAL_CXX14 #endif @@ -326,9 +336,16 @@ template struct optional_operations_base : optional_storage_base { template void assign(Opt &&rhs) { if (this->m_has_value) { if (rhs.m_has_value) { - get() = std::forward(rhs).get(); + this->m_value = std::forward(rhs).get(); + } else { + this->m_value.~T(); + this->m_has_value = false; } } + + if (rhs.m_has_value) { + construct(std::forward(rhs).get()); + } } TL_OPTIONAL_11_CONSTEXPR T &get() & { return this->m_value; } @@ -339,7 +356,7 @@ template struct optional_operations_base : optional_storage_base { #endif }; -template ::value> + template struct optional_copy_base : optional_operations_base { using optional_operations_base::optional_operations_base; }; @@ -362,11 +379,16 @@ struct optional_copy_base : optional_operations_base { optional_copy_base &operator=(optional_copy_base &&rhs) = default; }; + +#ifndef TL_OPTIONAL_GCC49 template ::value> struct optional_move_base : optional_copy_base { using optional_copy_base::optional_copy_base; }; - +#else + template + struct optional_move_base; + #endif template struct optional_move_base : optional_copy_base { using optional_copy_base::optional_copy_base; @@ -385,7 +407,7 @@ template struct optional_move_base : optional_copy_base { optional_move_base &operator=(optional_move_base &&rhs) = default; }; -template ::value> + template struct optional_copy_assign_base : optional_move_base { using optional_move_base::optional_move_base; }; @@ -399,23 +421,25 @@ struct optional_copy_assign_base : optional_move_base { optional_copy_assign_base(optional_copy_assign_base &&rhs) = default; optional_copy_assign_base &operator=(const optional_copy_assign_base &rhs) { - if (rhs.m_has_value) { - this->assign(rhs.get()); - } else { - this->reset(); - } + this->assign(rhs); } optional_copy_assign_base & operator=(optional_copy_assign_base &&rhs) = default; }; -template ::value> + +#ifndef TL_OPTIONAL_GCC49 +template ::value && std::is_trivially_move_constructible::value && std::is_trivially_move_assignable::value> struct optional_move_assign_base : optional_copy_assign_base { using optional_copy_assign_base::optional_copy_assign_base; }; +#else + template + struct optional_move_assign_base; +#endif -template -struct optional_move_assign_base : optional_copy_assign_base { + template + struct optional_move_assign_base : optional_copy_assign_base { using optional_copy_assign_base::optional_copy_assign_base; optional_move_assign_base() = default; @@ -426,11 +450,8 @@ struct optional_move_assign_base : optional_copy_assign_base { operator=(const optional_move_assign_base &rhs) noexcept( std::is_nothrow_move_constructible::value &&std::is_nothrow_move_assignable::value) { - if (rhs.m_has_value) { - this->assign(std::move(rhs.get())); - } else { - this->reset(); - } + this->assign(std::move(rhs)); + } optional_move_assign_base & operator=(optional_move_assign_base &&rhs) = default;