aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFelix Morgner <felix.morgner@gmail.com>2019-12-29 00:39:18 +0100
committerFelix Morgner <felix.morgner@gmail.com>2019-12-29 00:39:18 +0100
commitea7281aa5076c13f29cc76a565d95b2a339379d0 (patch)
tree1bab86487bca2c108fc696770ae54d236631e19a
parentdfa16015a4fc5f2a97bc8a248637e2e90f90f513 (diff)
downloadnewtype-ea7281aa5076c13f29cc76a565d95b2a339379d0.tar.xz
newtype-ea7281aa5076c13f29cc76a565d95b2a339379d0.zip
new_type: rework special member function bases
-rw-r--r--.vscode/settings.json4
-rw-r--r--include/newtype/new_type.hpp183
-rw-r--r--test/src/new_type_constructor_suite.cpp23
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