From 6ec9162bb52265ead31e1ff16bcf1aa417032753 Mon Sep 17 00:00:00 2001 From: Eric Niebler Date: Thu, 26 Jan 2017 14:17:16 -0800 Subject: [PATCH] Rework a bunch of the *tructible concepts, Movable requires object types (#66) --- include/stl2/detail/concepts/core.hpp | 2 +- .../detail/concepts/object/assignable.hpp | 11 +- .../stl2/detail/concepts/object/movable.hpp | 5 +- .../concepts/object/move_constructible.hpp | 131 ++++-------------- .../detail/concepts/object/semiregular.hpp | 14 +- include/stl2/detail/ebo_box.hpp | 3 +- include/stl2/detail/semiregular_box.hpp | 3 +- include/stl2/detail/temporary_vector.hpp | 4 +- include/stl2/optional.hpp | 4 +- test/concepts/object.cpp | 92 ++++++------ test/optional.cpp | 6 +- 11 files changed, 99 insertions(+), 176 deletions(-) diff --git a/include/stl2/detail/concepts/core.hpp b/include/stl2/detail/concepts/core.hpp index 9e7467822..e7750da9f 100644 --- a/include/stl2/detail/concepts/core.hpp +++ b/include/stl2/detail/concepts/core.hpp @@ -27,7 +27,7 @@ STL2_OPEN_NAMESPACE { concept bool _Is = _Valid && T::value; template class T, class...V> - concept bool _IsNot = !_Is; + concept bool _IsNot = _Valid && !T::value; // U is a cv/ref-qualified specialization of class template T. template class T> diff --git a/include/stl2/detail/concepts/object/assignable.hpp b/include/stl2/detail/concepts/object/assignable.hpp index 2ed829b5c..254a223b9 100644 --- a/include/stl2/detail/concepts/object/assignable.hpp +++ b/include/stl2/detail/concepts/object/assignable.hpp @@ -22,18 +22,21 @@ STL2_OPEN_NAMESPACE { /////////////////////////////////////////////////////////////////////////// // Assignable [concepts.lib.corelang.assignable] // + // Not to spec + // See https://github.com/ericniebler/stl2/issues/229 template constexpr bool __assignable = false; template requires - requires(T&& t, U&& u) { - STL2_EXACT_TYPE_CONSTRAINT((T&&)t = (U&&)u, T&); + requires(T& t, U&& u) { + STL2_EXACT_TYPE_CONSTRAINT(t = (U&&)u, T&); } - constexpr bool __assignable = true; + constexpr bool __assignable = true; template concept bool Assignable() { - return CommonReference() && + return Same&>() && + CommonReference() && __assignable; } diff --git a/include/stl2/detail/concepts/object/movable.hpp b/include/stl2/detail/concepts/object/movable.hpp index 469ed59bc..695c9a890 100644 --- a/include/stl2/detail/concepts/object/movable.hpp +++ b/include/stl2/detail/concepts/object/movable.hpp @@ -22,9 +22,12 @@ STL2_OPEN_NAMESPACE { /////////////////////////////////////////////////////////////////////////// // Movable [concepts.lib.object.movable] // + // Not to spec + // https://github.com/ericniebler/stl2/issues/310 template concept bool Movable() { - return MoveConstructible() && + return _Is && + MoveConstructible() && Assignable() && Swappable(); } diff --git a/include/stl2/detail/concepts/object/move_constructible.hpp b/include/stl2/detail/concepts/object/move_constructible.hpp index c13a393a5..72e42667f 100644 --- a/include/stl2/detail/concepts/object/move_constructible.hpp +++ b/include/stl2/detail/concepts/object/move_constructible.hpp @@ -26,8 +26,8 @@ STL2_OPEN_NAMESPACE { constexpr bool __addressable = false; template requires requires(T& t, const T& ct) { - STL2_EXACT_TYPE_CONSTRAINT(&t, T*); - STL2_EXACT_TYPE_CONSTRAINT(&ct, const T*); + STL2_EXACT_TYPE_CONSTRAINT(&t, add_pointer_t); + STL2_EXACT_TYPE_CONSTRAINT(&ct, add_pointer_t); // Axiom: &ct == addressof(ct) } constexpr bool __addressable = true; @@ -35,7 +35,7 @@ STL2_OPEN_NAMESPACE { namespace ext { template concept bool Addressable() { - return __addressable; + return _Is && __addressable; } } @@ -46,122 +46,44 @@ STL2_OPEN_NAMESPACE { constexpr bool Addressable = true; } - namespace detail { - template - constexpr bool is_complete_object = false; - - template <_Is T> - requires - sizeof(T) > 0 - constexpr bool is_complete_object = true; - - template - constexpr bool MustBeComplete() { - static_assert(is_complete_object, "Concept check for incomplete type T."); - return true; - } - } - /////////////////////////////////////////////////////////////////////////// // Destructible [concepts.lib.object.destructible] - // Not to spec: is_object and accepting the parameters by reference are - // necessary to prevent hard errors in the requires clause - // with odd types. - // - template - constexpr bool __destructible = false; - template - requires _Is && - _IsNot && - detail::MustBeComplete() && - requires(T& t, T* const p) { - { t.~T() } noexcept; - delete p; - delete[] p; - } - constexpr bool __destructible = true; + // Not to spec + // https://github.com/ericniebler/stl2/issues/301 + namespace models { + template + constexpr bool Destructible = + is_nothrow_destructible::value && __addressable; + } template concept bool Destructible() { - return ext::Addressable() && __destructible; - } - - namespace models { - template - constexpr bool Destructible = false; - __stl2::Destructible{T} - constexpr bool Destructible = true; + return models::Destructible; } /////////////////////////////////////////////////////////////////////////// // Constructible [concepts.lib.object.constructible] - // Extension: ConstructibleObject and BindableReference are user-visible. - // - namespace ext { -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Waddress" - template - constexpr bool __constructible_object = false; - template - requires requires(Args&&...args) { - T{ (Args&&)args... }; - new T{ (Args&&)args... }; - } - constexpr bool __constructible_object = true; - - template - concept bool ConstructibleObject = - Destructible() && __constructible_object; -#pragma GCC diagnostic pop - - // 20150718: Not to spec: spec is broken. - // FIXME: Correct wording. - template - concept bool BindableReference = - _Is && - // requires(Args&&...args) { T{ (Args&&)args... }; }; - // requires(Args&&...args) { T( (Args&&)args... ); }; - _Is; + // Not to spec + // See https://github.com/ericniebler/stl2/issues/301 + template + concept bool Constructible() { + return Destructible() && _Is; } namespace models { - template - constexpr bool ConstructibleObject = false; - __stl2::ext::ConstructibleObject{T, ...Args} - constexpr bool ConstructibleObject = true; - - template - constexpr bool BindableReference = false; - __stl2::ext::BindableReference{T, ...Args} - constexpr bool BindableReference = true; - - template - constexpr bool Constructible = - ConstructibleObject || - BindableReference; - } - - template - concept bool Constructible() { - return models::Constructible; + template + constexpr bool Constructible = false; + __stl2::Constructible{T, ...Args} + constexpr bool Constructible = true; } /////////////////////////////////////////////////////////////////////////// // DefaultConstructible [concepts.lib.object.defaultconstructible] - // Note: Due to implementation variance around DR1518, may not correctly - // enforce the requirement that the default constructor be non-explicit. - // - template - constexpr bool __default_constructible = false; - template - requires requires(const std::size_t n) { - new T[n]{}; // not required to be equality preserving - } - constexpr bool __default_constructible = true; - + // Not to spec + // https://github.com/ericniebler/stl2/issues/301 template concept bool DefaultConstructible() { - return Constructible() && __default_constructible; + return Constructible(); } namespace models { @@ -173,11 +95,12 @@ STL2_OPEN_NAMESPACE { /////////////////////////////////////////////////////////////////////////// // MoveConstructible [concepts.lib.object.moveconstructible] - // + // Not to spec + // https://github.com/ericniebler/stl2/issues/313 template concept bool MoveConstructible() { - return Constructible&&>() && - ConvertibleTo&&, T>(); + return Constructible() && + ConvertibleTo(); } namespace models { diff --git a/include/stl2/detail/concepts/object/semiregular.hpp b/include/stl2/detail/concepts/object/semiregular.hpp index ba10b7542..32a2095f1 100644 --- a/include/stl2/detail/concepts/object/semiregular.hpp +++ b/include/stl2/detail/concepts/object/semiregular.hpp @@ -23,14 +23,18 @@ STL2_OPEN_NAMESPACE { /////////////////////////////////////////////////////////////////////////// // CopyConstructible [concepts.lib.object.copyconstructible] - // + // Not to spec + // https://github.com/ericniebler/stl2/issues/301 + // https://github.com/ericniebler/stl2/issues/313 template concept bool CopyConstructible() { return MoveConstructible() && - Constructible&>() && - ConvertibleTo&, T>() && - ConvertibleTo&, T>() && - ConvertibleTo&&, T>(); + Constructible() && + Constructible() && + Constructible() && + ConvertibleTo() && + ConvertibleTo() && + ConvertibleTo(); } namespace models { diff --git a/include/stl2/detail/ebo_box.hpp b/include/stl2/detail/ebo_box.hpp index 6959b24d7..ee5902643 100644 --- a/include/stl2/detail/ebo_box.hpp +++ b/include/stl2/detail/ebo_box.hpp @@ -24,6 +24,7 @@ STL2_OPEN_NAMESPACE { std::is_class::value && !std::is_final::value; template + requires _Is class ebo_box { public: ebo_box() = default; @@ -62,7 +63,7 @@ STL2_OPEN_NAMESPACE { }; template - requires __non_final_class + requires _Is && __non_final_class class ebo_box : private T { public: ebo_box() = default; diff --git a/include/stl2/detail/semiregular_box.hpp b/include/stl2/detail/semiregular_box.hpp index 3631961cc..8244e6fa2 100644 --- a/include/stl2/detail/semiregular_box.hpp +++ b/include/stl2/detail/semiregular_box.hpp @@ -20,7 +20,8 @@ STL2_OPEN_NAMESPACE { namespace detail { - Destructible{T} + template + requires _Is class semiregular_box { public: semiregular_box() = default; diff --git a/include/stl2/detail/temporary_vector.hpp b/include/stl2/detail/temporary_vector.hpp index af25bc558..95c23d5f4 100644 --- a/include/stl2/detail/temporary_vector.hpp +++ b/include/stl2/detail/temporary_vector.hpp @@ -90,6 +90,7 @@ STL2_OPEN_NAMESPACE { }; template + requires _Is class temporary_vector { T* begin_ = nullptr; T* end_ = nullptr; @@ -159,7 +160,8 @@ STL2_OPEN_NAMESPACE { { emplace_back(__stl2::move(t)); } }; - Destructible{T} + template + requires _Is temporary_vector make_temporary_vector(temporary_buffer& buf) { return {buf}; } diff --git a/include/stl2/optional.hpp b/include/stl2/optional.hpp index 3e60d5380..92e3d9a6d 100644 --- a/include/stl2/optional.hpp +++ b/include/stl2/optional.hpp @@ -46,7 +46,7 @@ STL2_OPEN_NAMESPACE { }; template - requires models::Destructible + requires models::Destructible && _Is class optional; namespace __optional { @@ -264,7 +264,7 @@ STL2_OPEN_NAMESPACE { } // namespace ext template - requires models::Destructible + requires models::Destructible && _Is class optional : public meta::_t> , detail::smf_control::copy> diff --git a/test/concepts/object.cpp b/test/concepts/object.cpp index a49346e58..87f0942c1 100644 --- a/test/concepts/object.cpp +++ b/test/concepts/object.cpp @@ -16,14 +16,6 @@ namespace models { template constexpr bool Destructible = ranges::Destructible(); -template -constexpr bool ConstructibleObject = - ranges::concepts::models(); - -template -constexpr bool BindableReference = - ranges::concepts::models(); - template constexpr bool Constructible = ranges::Constructible(); @@ -82,10 +74,18 @@ struct indestructible { ~indestructible() = delete; }; +struct throwing_destructor { + ~throwing_destructor() noexcept(false); +}; + struct explicit_default { explicit explicit_default() {} }; +struct deleted_default { + deleted_default() = delete; +}; + struct explicit_move { explicit_move() = default; explicit explicit_move(explicit_move&&) = default; @@ -133,17 +133,19 @@ struct XXX CONCEPT_ASSERT(models::Destructible); CONCEPT_ASSERT(models::Destructible); CONCEPT_ASSERT(!models::Destructible); -CONCEPT_ASSERT(!models::Destructible); +CONCEPT_ASSERT(models::Destructible); CONCEPT_ASSERT(!models::Destructible); CONCEPT_ASSERT(models::Destructible); -CONCEPT_ASSERT(!models::Destructible); +CONCEPT_ASSERT(models::Destructible); CONCEPT_ASSERT(!models::Destructible); -CONCEPT_ASSERT(!models::Destructible); +CONCEPT_ASSERT(models::Destructible); CONCEPT_ASSERT(models::Destructible); -CONCEPT_ASSERT(!models::Destructible); +CONCEPT_ASSERT(!models::Addressable); +CONCEPT_ASSERT(models::Destructible); CONCEPT_ASSERT(models::Destructible); CONCEPT_ASSERT(models::Destructible); CONCEPT_ASSERT(!models::Destructible); +CONCEPT_ASSERT(!models::Destructible); #if 0 // ill-formed (hard error) @@ -162,17 +164,11 @@ CONCEPT_ASSERT(!models::Constructible); CONCEPT_ASSERT(!models::Constructible); CONCEPT_ASSERT(!models::Constructible); CONCEPT_ASSERT(!models::Constructible); -CONCEPT_ASSERT(!models::Constructible); +CONCEPT_ASSERT(models::Constructible); CONCEPT_ASSERT(!models::Constructible); CONCEPT_ASSERT(models::Constructible); CONCEPT_ASSERT(!models::Constructible); -CONCEPT_ASSERT(models::ConstructibleObject); -CONCEPT_ASSERT(models::ConstructibleObject); -CONCEPT_ASSERT(models::ConstructibleObject); -CONCEPT_ASSERT(models::ConstructibleObject); -CONCEPT_ASSERT(models::ConstructibleObject); -CONCEPT_ASSERT(models::ConstructibleObject); CONCEPT_ASSERT(models::Constructible); CONCEPT_ASSERT(models::Constructible); CONCEPT_ASSERT(models::Constructible); @@ -180,12 +176,6 @@ CONCEPT_ASSERT(models::Constructible); CONCEPT_ASSERT(models::Constructible); CONCEPT_ASSERT(models::Constructible); -CONCEPT_ASSERT(models::ConstructibleObject); -CONCEPT_ASSERT(models::ConstructibleObject); -CONCEPT_ASSERT(models::ConstructibleObject); -CONCEPT_ASSERT(models::ConstructibleObject); -CONCEPT_ASSERT(models::ConstructibleObject); -CONCEPT_ASSERT(models::ConstructibleObject); CONCEPT_ASSERT(models::Constructible); CONCEPT_ASSERT(models::Constructible); CONCEPT_ASSERT(models::Constructible); @@ -193,12 +183,6 @@ CONCEPT_ASSERT(models::Constructible); CONCEPT_ASSERT(models::Constructible); CONCEPT_ASSERT(models::Constructible); -CONCEPT_ASSERT(!models::BindableReference); -CONCEPT_ASSERT(models::BindableReference); -CONCEPT_ASSERT(!models::BindableReference); -CONCEPT_ASSERT(!models::BindableReference); -CONCEPT_ASSERT(!models::BindableReference); -CONCEPT_ASSERT(!models::BindableReference); CONCEPT_ASSERT(!models::Constructible); CONCEPT_ASSERT(models::Constructible); CONCEPT_ASSERT(!models::Constructible); @@ -206,12 +190,6 @@ CONCEPT_ASSERT(!models::Constructible); CONCEPT_ASSERT(!models::Constructible); CONCEPT_ASSERT(!models::Constructible); -CONCEPT_ASSERT(models::BindableReference); -CONCEPT_ASSERT(models::BindableReference); -CONCEPT_ASSERT(models::BindableReference); -CONCEPT_ASSERT(models::BindableReference); -CONCEPT_ASSERT(models::BindableReference); -CONCEPT_ASSERT(models::BindableReference); CONCEPT_ASSERT(models::Constructible); CONCEPT_ASSERT(models::Constructible); CONCEPT_ASSERT(models::Constructible); @@ -219,12 +197,6 @@ CONCEPT_ASSERT(models::Constructible); CONCEPT_ASSERT(models::Constructible); CONCEPT_ASSERT(models::Constructible); -CONCEPT_ASSERT(models::BindableReference); -CONCEPT_ASSERT(!models::BindableReference); -CONCEPT_ASSERT(models::BindableReference); -CONCEPT_ASSERT(!models::BindableReference); -CONCEPT_ASSERT(!models::BindableReference); -CONCEPT_ASSERT(!models::BindableReference); CONCEPT_ASSERT(models::Constructible); CONCEPT_ASSERT(!models::Constructible); CONCEPT_ASSERT(models::Constructible); @@ -232,12 +204,6 @@ CONCEPT_ASSERT(!models::Constructible); CONCEPT_ASSERT(!models::Constructible); CONCEPT_ASSERT(!models::Constructible); -CONCEPT_ASSERT(models::BindableReference); -CONCEPT_ASSERT(!models::BindableReference); -CONCEPT_ASSERT(models::BindableReference); -CONCEPT_ASSERT(models::BindableReference); -CONCEPT_ASSERT(!models::BindableReference); -CONCEPT_ASSERT(models::BindableReference); CONCEPT_ASSERT(models::Constructible); CONCEPT_ASSERT(!models::Constructible); CONCEPT_ASSERT(models::Constructible); @@ -256,7 +222,7 @@ CONCEPT_ASSERT(!models::DefaultConstructible); CONCEPT_ASSERT(models::DefaultConstructible); CONCEPT_ASSERT(!models::DefaultConstructible); CONCEPT_ASSERT(!models::DefaultConstructible); -CONCEPT_ASSERT(!models::DefaultConstructible); +CONCEPT_ASSERT(models::DefaultConstructible); CONCEPT_ASSERT(!models::DefaultConstructible); // It's hard to catch explicit default constructors, see @@ -264,6 +230,7 @@ CONCEPT_ASSERT(!models::DefaultConstructible); // CONCEPT_ASSERT(!models::DefaultConstructible); CONCEPT_ASSERT(models::DefaultConstructible); CONCEPT_ASSERT(models::DefaultConstructible); +CONCEPT_ASSERT(!models::DefaultConstructible); CONCEPT_ASSERT(!models::MoveConstructible); CONCEPT_ASSERT(models::MoveConstructible); @@ -275,7 +242,6 @@ CONCEPT_ASSERT(models::MoveConstructible); CONCEPT_ASSERT(models::MoveConstructible); CONCEPT_ASSERT(models::MoveConstructible); -CONCEPT_ASSERT(models::ConstructibleObject); CONCEPT_ASSERT(models::Constructible); CONCEPT_ASSERT(models::MoveConstructible); CONCEPT_ASSERT(models::MoveConstructible); @@ -310,6 +276,22 @@ CONCEPT_ASSERT(!models::CopyConstructible); CONCEPT_ASSERT(models::CopyConstructible); CONCEPT_ASSERT(!models::CopyConstructible); +// https://github.com/ericniebler/stl2/issues/301 +struct not_mutable_ref { + not_mutable_ref() = default; + not_mutable_ref(const not_mutable_ref&) = default; + not_mutable_ref(not_mutable_ref&&) = default; + not_mutable_ref(not_mutable_ref&) = delete; +}; +struct not_const_ref_ref { + not_const_ref_ref() = default; + not_const_ref_ref(const not_const_ref_ref&) = default; + not_const_ref_ref(not_const_ref_ref&&) = default; + not_const_ref_ref(const not_const_ref_ref&&) = delete; +}; +CONCEPT_ASSERT(!models::CopyConstructible); +CONCEPT_ASSERT(!models::CopyConstructible); + CONCEPT_ASSERT(models::Movable); CONCEPT_ASSERT(!models::Movable); CONCEPT_ASSERT(models::Movable); @@ -354,12 +336,16 @@ CONCEPT_ASSERT(!models::Regular); CONCEPT_ASSERT(!models::Regular); CONCEPT_ASSERT(!models::Regular); -CONCEPT_ASSERT(models::ConstructibleObject>); CONCEPT_ASSERT(models::Constructible>); CONCEPT_ASSERT(models::DefaultConstructible>); -CONCEPT_ASSERT(models::ConstructibleObject); CONCEPT_ASSERT(models::Constructible); CONCEPT_ASSERT(models::DefaultConstructible); +// https://github.com/ericniebler/stl2/issues/301 +CONCEPT_ASSERT(!models::Constructible); + +// https://github.com/ericniebler/stl2/issues/310 +CONCEPT_ASSERT(!models::Movable); + int main() {} diff --git a/test/optional.cpp b/test/optional.cpp index 147518360..fb81fa8f0 100644 --- a/test/optional.cpp +++ b/test/optional.cpp @@ -226,11 +226,11 @@ int main() { static_assert(models::Constructible); static_assert(models::ConvertibleTo); - static_assert(!models::ConvertibleTo); - static_assert(!models::Constructible); + static_assert(models::ConvertibleTo); + static_assert(models::Constructible); static_assert(models::ConvertibleTo); - static_assert(!models::Constructible); // narrowing + static_assert(models::Constructible); static_assert(!models::Swappable); }