diff options
| author | Felix Morgner <felix.morgner@gmail.com> | 2019-12-29 00:39:18 +0100 |
|---|---|---|
| committer | Felix Morgner <felix.morgner@gmail.com> | 2019-12-29 00:39:18 +0100 |
| commit | ea7281aa5076c13f29cc76a565d95b2a339379d0 (patch) | |
| tree | 1bab86487bca2c108fc696770ae54d236631e19a | |
| parent | dfa16015a4fc5f2a97bc8a248637e2e90f90f513 (diff) | |
| download | newtype-ea7281aa5076c13f29cc76a565d95b2a339379d0.tar.xz newtype-ea7281aa5076c13f29cc76a565d95b2a339379d0.zip | |
new_type: rework special member function bases
| -rw-r--r-- | .vscode/settings.json | 4 | ||||
| -rw-r--r-- | include/newtype/new_type.hpp | 183 | ||||
| -rw-r--r-- | 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<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 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<nt_old, OldType>)); } + auto a_new__type_instance_can_be_copy_constructed_if_the_base_type_can_be_copy_constructed() -> void + { + using type_alias = nt::new_type<int, struct tag_type>; + ASSERT((std::is_copy_constructible_v<type_alias>)); + } + + 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<not_copy_constructible, struct tag_type>; + ASSERT(!(std::is_copy_constructible_v<type_alias>)); + } + } // namespace constructor_tests auto new_type_constructor_suite() -> std::pair<cute::suite, std::string> @@ -63,6 +84,8 @@ auto new_type_constructor_suite() -> std::pair<cute::suite, std::string> KAWAII(a_new__type_based_on_a_fundamental_type_can_be_constructed_with_a_value_of_fundamental_type<float>), KAWAII(a_new__type_based_on_a_fundamental_type_can_be_constructed_with_a_value_of_fundamental_type<double>), KAWAII(a_new__type_based_on_a_fundamental_type_can_be_constructed_with_a_value_of_fundamental_type<long double>), + 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 |
