From ea7281aa5076c13f29cc76a565d95b2a339379d0 Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Sun, 29 Dec 2019 00:39:18 +0100 Subject: new_type: rework special member function bases --- .vscode/settings.json | 4 +- include/newtype/new_type.hpp | 183 ++++++++++++++++++++++---------- test/src/new_type_constructor_suite.cpp | 23 ++++ 3 files changed, 152 insertions(+), 58 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index fd771a0..f869c8c 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -60,7 +60,9 @@ "cfenv": "cpp", "cinttypes": "cpp", "typeinfo": "cpp", - "valarray": "cpp" + "valarray": "cpp", + "*.ipp": "cpp", + "bitset": "cpp" }, "cmake.configureArguments": "-DCMAKE_EXPORT_COMPILE_COMMANDS=YES", "cmake.cpptools.intelliSenseMode": "gcc-x64", 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> + template struct new_type_storage { - constexpr new_type_storage() noexcept(std::is_nothrow_default_constructible_v) = default; - - constexpr explicit new_type_storage(BaseType const & value) noexcept(std::is_nothrow_copy_constructible_v) - : m_value{value} + constexpr new_type_storage() noexcept(std::is_nothrow_default_constructible_v) + : m_value{} { } - constexpr explicit new_type_storage(BaseType && value) noexcept(std::is_nothrow_move_constructible_v) - : m_value{std::move(value)} + template + constexpr explicit new_type_storage(ArgumentType && value) noexcept(std::is_nothrow_constructible_v) + : m_value{std::forward(value)} { } - /** - * Retrieve the base type value contained in this @p new_type - */ - auto constexpr decay() const noexcept(std::is_nothrow_copy_constructible_v) -> BaseType - { - return m_value; - } + BaseType m_value; + }; - protected: - BaseType m_value{}; + template> + struct new_type_constructor : new_type_storage + { + using new_type_storage::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 - struct new_type_storage + struct new_type_constructor : new_type_storage { - constexpr new_type_storage() = delete; + using new_type_storage::new_type_storage; - constexpr explicit new_type_storage(BaseType const & value) noexcept(std::is_nothrow_copy_constructible_v) - : m_value{value} - { - } + new_type_constructor() = delete; + }; - constexpr explicit new_type_storage(BaseType && value) noexcept(std::is_nothrow_move_constructible_v) - : m_value{std::move(value)} - { - } + template> + struct new_type_copy_constructor : new_type_constructor + { + using new_type_constructor::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 - { - 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 + struct new_type_copy_constructor : new_type_constructor + { + using new_type_constructor::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> + struct new_type_move_constructor : new_type_copy_constructor + { + using new_type_copy_constructor::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 + struct new_type_move_constructor : new_type_copy_constructor + { + using new_type_copy_constructor::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> + struct new_type_copy_assignment : new_type_move_constructor + { + using new_type_move_constructor::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 + struct new_type_copy_assignment : new_type_move_constructor + { + using new_type_move_constructor::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> + struct new_type_move_assignment : new_type_copy_assignment + { + using new_type_copy_assignment::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 + struct new_type_move_assignment : new_type_copy_assignment + { + using new_type_copy_assignment::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 - class new_type : public impl::new_type_storage + class new_type : impl::new_type_move_assignment { - using storage = impl::new_type_storage; - - using storage::storage; + using super = impl::new_type_move_assignment; template) = default; + + constexpr new_type(new_type const &) noexcept(std::is_nothrow_copy_constructible_v) = default; + + constexpr new_type(new_type &&) noexcept(std::is_nothrow_move_constructible_v) = default; + + constexpr explicit new_type(BaseType const & value) noexcept(std::is_nothrow_copy_constructible_v) + : super{value} + { + } + + constexpr explicit new_type(BaseType const && value) noexcept(std::is_nothrow_move_constructible_v) + : super{std::move(value)} + { + } + + auto constexpr operator=(new_type const &) noexcept(std::is_nothrow_copy_assignable_v) -> new_type & = default; + + auto constexpr operator=(new_type &&) noexcept(std::is_nothrow_move_assignable_v) -> new_type & = default; + + auto constexpr decay() const noexcept(std::is_nothrow_copy_constructible_v) -> BaseType + { + return this->m_value; + } /** * Convert this instance into the equivalent base type value diff --git a/test/src/new_type_constructor_suite.cpp b/test/src/new_type_constructor_suite.cpp index fa4c0b7..27b7452 100644 --- a/test/src/new_type_constructor_suite.cpp +++ b/test/src/new_type_constructor_suite.cpp @@ -38,6 +38,27 @@ inline namespace constructor_tests ASSERT((std::is_constructible_v)); } + auto a_new__type_instance_can_be_copy_constructed_if_the_base_type_can_be_copy_constructed() -> void + { + using type_alias = nt::new_type; + ASSERT((std::is_copy_constructible_v)); + } + + auto a_new__type_instance_can_not_be_copy_constructed_if_the_base_type_can_not_be_copy_constructed() -> void + { + struct not_copy_constructible + { + not_copy_constructible() = default; + not_copy_constructible(not_copy_constructible const &) = delete; + not_copy_constructible(not_copy_constructible &&) = default; + auto operator=(not_copy_constructible const &) -> not_copy_constructible & = default; + auto operator=(not_copy_constructible &&) -> not_copy_constructible & = default; + }; + + using type_alias = nt::new_type; + ASSERT(!(std::is_copy_constructible_v)); + } + } // namespace constructor_tests auto new_type_constructor_suite() -> std::pair @@ -63,6 +84,8 @@ auto new_type_constructor_suite() -> std::pair KAWAII(a_new__type_based_on_a_fundamental_type_can_be_constructed_with_a_value_of_fundamental_type), KAWAII(a_new__type_based_on_a_fundamental_type_can_be_constructed_with_a_value_of_fundamental_type), KAWAII(a_new__type_based_on_a_fundamental_type_can_be_constructed_with_a_value_of_fundamental_type), + KAWAII(a_new__type_instance_can_be_copy_constructed_if_the_base_type_can_be_copy_constructed), + KAWAII(a_new__type_instance_can_not_be_copy_constructed_if_the_base_type_can_not_be_copy_constructed), }, "new_type Constructor Tests"}; } \ No newline at end of file -- cgit v1.2.3