aboutsummaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
Diffstat (limited to 'include')
-rw-r--r--include/newtype/new_type.hpp183
1 files changed, 126 insertions, 57 deletions
diff --git a/include/newtype/new_type.hpp b/include/newtype/new_type.hpp
index ee07cff..57674cb 100644
--- a/include/newtype/new_type.hpp
+++ b/include/newtype/new_type.hpp
@@ -15,75 +15,123 @@ namespace nt
namespace impl
{
- /**
- * This class forms the a base type of nt::new_type and provides its storage
- *
- * This specialization enables the default constructor for cases in which @p BaseType is default constructible
- *
- * @tparam BaseType An existing type that shall aliased
- * @tparam TagType A unique type to identify this nt::new_type
- */
- template<typename BaseType, typename TagType, bool = std::is_default_constructible_v<BaseType>>
+ template<typename BaseType, typename TagType>
struct new_type_storage
{
- constexpr new_type_storage() noexcept(std::is_nothrow_default_constructible_v<BaseType>) = default;
-
- constexpr explicit new_type_storage(BaseType const & value) noexcept(std::is_nothrow_copy_constructible_v<BaseType>)
- : m_value{value}
+ constexpr new_type_storage() noexcept(std::is_nothrow_default_constructible_v<BaseType>)
+ : m_value{}
{
}
- constexpr explicit new_type_storage(BaseType && value) noexcept(std::is_nothrow_move_constructible_v<BaseType>)
- : m_value{std::move(value)}
+ template<typename ArgumentType>
+ constexpr explicit new_type_storage(ArgumentType && value) noexcept(std::is_nothrow_constructible_v<BaseType, ArgumentType>)
+ : m_value{std::forward<ArgumentType>(value)}
{
}
- /**
- * Retrieve the base type value contained in this @p new_type
- */
- auto constexpr decay() const noexcept(std::is_nothrow_copy_constructible_v<BaseType>) -> BaseType
- {
- return m_value;
- }
+ BaseType m_value;
+ };
- protected:
- BaseType m_value{};
+ template<typename BaseType, typename TagType, bool = std::is_default_constructible_v<BaseType>>
+ struct new_type_constructor : new_type_storage<BaseType, TagType>
+ {
+ using new_type_storage<BaseType, TagType>::new_type_storage;
};
- /**
- * This class forms the a base type of nt::new_type and provides its storage
- *
- * This specialization explicitly deletes the default constructor for cases in which @p BaseType is not default
- * constructible
- *
- * @tparam BaseType An existing type that shall aliased
- * @tparam TagType A unique type to identify this nt::new_type
- */
template<typename BaseType, typename TagType>
- struct new_type_storage<BaseType, TagType, false>
+ struct new_type_constructor<BaseType, TagType, false> : new_type_storage<BaseType, TagType>
{
- constexpr new_type_storage() = delete;
+ using new_type_storage<BaseType, TagType>::new_type_storage;
- constexpr explicit new_type_storage(BaseType const & value) noexcept(std::is_nothrow_copy_constructible_v<BaseType>)
- : m_value{value}
- {
- }
+ new_type_constructor() = delete;
+ };
- constexpr explicit new_type_storage(BaseType && value) noexcept(std::is_nothrow_move_constructible_v<BaseType>)
- : m_value{std::move(value)}
- {
- }
+ template<typename BaseType, typename TagType, bool = std::is_copy_constructible_v<BaseType>>
+ struct new_type_copy_constructor : new_type_constructor<BaseType, TagType>
+ {
+ using new_type_constructor<BaseType, TagType>::new_type_constructor;
- /**
- * Retrieve the base type value contained in this @p new_type
- */
- auto constexpr decay() const noexcept(std::is_nothrow_copy_constructible_v<BaseType>) -> BaseType
- {
- return m_value;
- }
+ constexpr new_type_copy_constructor(new_type_copy_constructor const &) = default;
+ constexpr new_type_copy_constructor(new_type_copy_constructor &&) = default;
+ auto constexpr operator=(new_type_copy_constructor &) -> new_type_copy_constructor & = default;
+ auto constexpr operator=(new_type_copy_constructor &&) -> new_type_copy_constructor & = default;
+ };
- protected:
- BaseType m_value;
+ template<typename BaseType, typename TagType>
+ struct new_type_copy_constructor<BaseType, TagType, false> : new_type_constructor<BaseType, TagType>
+ {
+ using new_type_constructor<BaseType, TagType>::new_type_constructor;
+
+ constexpr new_type_copy_constructor(new_type_copy_constructor const &) = delete;
+ constexpr new_type_copy_constructor(new_type_copy_constructor &&) = default;
+ auto constexpr operator=(new_type_copy_constructor &) -> new_type_copy_constructor & = default;
+ auto constexpr operator=(new_type_copy_constructor &&) -> new_type_copy_constructor & = default;
+ };
+
+ template<typename BaseType, typename TagType, bool = std::is_move_constructible_v<BaseType>>
+ struct new_type_move_constructor : new_type_copy_constructor<BaseType, TagType>
+ {
+ using new_type_copy_constructor<BaseType, TagType>::new_type_copy_constructor;
+
+ constexpr new_type_move_constructor(new_type_move_constructor const &) = default;
+ constexpr new_type_move_constructor(new_type_move_constructor &&) = default;
+ auto constexpr operator=(new_type_move_constructor &) -> new_type_move_constructor & = default;
+ auto constexpr operator=(new_type_move_constructor &&) -> new_type_move_constructor & = default;
+ };
+
+ template<typename BaseType, typename TagType>
+ struct new_type_move_constructor<BaseType, TagType, false> : new_type_copy_constructor<BaseType, TagType>
+ {
+ using new_type_copy_constructor<BaseType, TagType>::new_type_copy_constructor;
+
+ constexpr new_type_move_constructor(new_type_move_constructor const &) = default;
+ constexpr new_type_move_constructor(new_type_move_constructor &&) = delete;
+ auto constexpr operator=(new_type_move_constructor &) -> new_type_move_constructor & = default;
+ auto constexpr operator=(new_type_move_constructor &&) -> new_type_move_constructor & = default;
+ };
+
+ template<typename BaseType, typename TagType, bool = std::is_copy_assignable_v<BaseType>>
+ struct new_type_copy_assignment : new_type_move_constructor<BaseType, TagType>
+ {
+ using new_type_move_constructor<BaseType, TagType>::new_type_move_constructor;
+
+ constexpr new_type_copy_assignment(new_type_copy_assignment const &) = default;
+ constexpr new_type_copy_assignment(new_type_copy_assignment &&) = default;
+ auto constexpr operator=(new_type_copy_assignment &) -> new_type_copy_assignment & = default;
+ auto constexpr operator=(new_type_copy_assignment &&) -> new_type_copy_assignment & = default;
+ };
+
+ template<typename BaseType, typename TagType>
+ struct new_type_copy_assignment<BaseType, TagType, false> : new_type_move_constructor<BaseType, TagType>
+ {
+ using new_type_move_constructor<BaseType, TagType>::new_type_move_constructor;
+
+ constexpr new_type_copy_assignment(new_type_copy_assignment const &) = default;
+ constexpr new_type_copy_assignment(new_type_copy_assignment &&) = default;
+ auto constexpr operator=(new_type_copy_assignment &) -> new_type_copy_assignment & = default;
+ auto constexpr operator=(new_type_copy_assignment &&) -> new_type_copy_assignment & = delete;
+ };
+
+ template<typename BaseType, typename TagType, bool = std::is_move_assignable_v<BaseType>>
+ struct new_type_move_assignment : new_type_copy_assignment<BaseType, TagType>
+ {
+ using new_type_copy_assignment<BaseType, TagType>::new_type_copy_assignment;
+
+ constexpr new_type_move_assignment(new_type_move_assignment const &) = default;
+ constexpr new_type_move_assignment(new_type_move_assignment &&) = default;
+ auto constexpr operator=(new_type_move_assignment &) -> new_type_move_assignment & = default;
+ auto constexpr operator=(new_type_move_assignment &&) -> new_type_move_assignment & = default;
+ };
+
+ template<typename BaseType, typename TagType>
+ struct new_type_move_assignment<BaseType, TagType, false> : new_type_copy_assignment<BaseType, TagType>
+ {
+ using new_type_copy_assignment<BaseType, TagType>::new_type_copy_assignment;
+
+ constexpr new_type_move_assignment(new_type_move_assignment const &) = default;
+ constexpr new_type_move_assignment(new_type_move_assignment &&) = default;
+ auto constexpr operator=(new_type_move_assignment &) -> new_type_move_assignment & = default;
+ auto constexpr operator=(new_type_move_assignment &&) -> new_type_move_assignment & = delete;
};
} // namespace impl
@@ -97,11 +145,9 @@ namespace nt
* @tparam DervivationClause An nt::derivation_clause describing which features shall be automatically derived for the new type alias
*/
template<typename BaseType, typename TagType, auto DerivationClause = deriving()>
- class new_type : public impl::new_type_storage<BaseType, TagType>
+ class new_type : impl::new_type_move_assignment<BaseType, TagType>
{
- using storage = impl::new_type_storage<BaseType, TagType>;
-
- using storage::storage;
+ using super = impl::new_type_move_assignment<BaseType, TagType>;
template<typename BaseTypeT,
typename TagTypeT,
@@ -136,7 +182,30 @@ namespace nt
*/
auto constexpr static derivation_clause = DerivationClause;
- using storage::decay;
+ constexpr new_type() noexcept(std::is_nothrow_default_constructible_v<BaseType>) = default;
+
+ constexpr new_type(new_type const &) noexcept(std::is_nothrow_copy_constructible_v<BaseType>) = default;
+
+ constexpr new_type(new_type &&) noexcept(std::is_nothrow_move_constructible_v<BaseType>) = default;
+
+ constexpr explicit new_type(BaseType const & value) noexcept(std::is_nothrow_copy_constructible_v<BaseType>)
+ : super{value}
+ {
+ }
+
+ constexpr explicit new_type(BaseType const && value) noexcept(std::is_nothrow_move_constructible_v<BaseType>)
+ : super{std::move(value)}
+ {
+ }
+
+ auto constexpr operator=(new_type const &) noexcept(std::is_nothrow_copy_assignable_v<BaseType>) -> new_type & = default;
+
+ auto constexpr operator=(new_type &&) noexcept(std::is_nothrow_move_assignable_v<BaseType>) -> new_type & = default;
+
+ auto constexpr decay() const noexcept(std::is_nothrow_copy_constructible_v<BaseType>) -> BaseType
+ {
+ return this->m_value;
+ }
/**
* Convert this instance into the equivalent base type value