Skip to content

Commit

Permalink
rework a bunch of the *tructible concepts, Movable requires object types
Browse files Browse the repository at this point in the history
  • Loading branch information
ericniebler committed Jan 25, 2017
1 parent 0bc0999 commit c946f3e
Show file tree
Hide file tree
Showing 11 changed files with 67 additions and 166 deletions.
2 changes: 1 addition & 1 deletion include/stl2/detail/concepts/core.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ STL2_OPEN_NAMESPACE {
concept bool _Is = _Valid<T, U, V...> && T<U, V...>::value;

template <class U, template <class...> class T, class...V>
concept bool _IsNot = !_Is<U, T, V...>;
concept bool _IsNot = _Valid<T, U, V...> && !T<U, V...>::value;

// U is a cv/ref-qualified specialization of class template T.
template <class U, template <class...> class T>
Expand Down
11 changes: 7 additions & 4 deletions include/stl2/detail/concepts/object/assignable.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,18 +22,21 @@ STL2_OPEN_NAMESPACE {
///////////////////////////////////////////////////////////////////////////
// Assignable [concepts.lib.corelang.assignable]
//
// Not to spec
// See https://github.com/ericniebler/stl2/issues/229
template <class, class>
constexpr bool __assignable = false;
template <class T, class U>
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<T, U> = true;
constexpr bool __assignable<T&, U> = true;

template <class T, class U>
concept bool Assignable() {
return CommonReference<const T&, const U&>() &&
return Same<T, decay_t<T>&>() &&
CommonReference<T, const U&>() &&
__assignable<T, U>;
}

Expand Down
5 changes: 4 additions & 1 deletion include/stl2/detail/concepts/object/movable.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,12 @@ STL2_OPEN_NAMESPACE {
///////////////////////////////////////////////////////////////////////////
// Movable [concepts.lib.object.movable]
//
// Not to spec
// https://github.com/ericniebler/stl2/issues/310
template <class T>
concept bool Movable() {
return MoveConstructible<T>() &&
return _Is<T, is_object> &&
MoveConstructible<T>() &&
Assignable<T&, T&&>() &&
Swappable<T&>();
}
Expand Down
123 changes: 24 additions & 99 deletions include/stl2/detail/concepts/object/move_constructible.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ STL2_OPEN_NAMESPACE {
//
template <class>
constexpr bool __addressable = false;
template <class T>
constexpr bool __addressable<T&> = true;
template <class T>
constexpr bool __addressable<T&&> = true;
template <class T>
requires requires(T& t, const T& ct) {
STL2_EXACT_TYPE_CONSTRAINT(&t, T*);
Expand All @@ -35,7 +39,7 @@ STL2_OPEN_NAMESPACE {
namespace ext {
template <class T>
concept bool Addressable() {
return __addressable<T>;
return _Is<T, is_object> && __addressable<T>;
}
}

Expand All @@ -46,122 +50,43 @@ STL2_OPEN_NAMESPACE {
constexpr bool Addressable<T> = true;
}

namespace detail {
template <class>
constexpr bool is_complete_object = false;

template <_Is<is_object> T>
requires
sizeof(T) > 0
constexpr bool is_complete_object<T> = true;

template <class T>
constexpr bool MustBeComplete() {
static_assert(is_complete_object<T>, "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 <class>
constexpr bool __destructible = false;
template <class T>
requires _Is<T, is_object> &&
_IsNot<T, is_array> &&
detail::MustBeComplete<T>() &&
requires(T& t, T* const p) {
{ t.~T() } noexcept;
delete p;
delete[] p;
}
constexpr bool __destructible<T> = true;
// Not to spec
// https://github.com/ericniebler/stl2/issues/301
namespace models {
template <class T>
constexpr bool Destructible = is_nothrow_destructible<T>::value && __addressable<T>;
}

template <class T>
concept bool Destructible() {
return ext::Addressable<T>() && __destructible<T>;
}

namespace models {
template <class>
constexpr bool Destructible = false;
__stl2::Destructible{T}
constexpr bool Destructible<T> = true;
return models::Destructible<T>;
}

///////////////////////////////////////////////////////////////////////////
// Constructible [concepts.lib.object.constructible]
// Extension: ConstructibleObject and BindableReference are user-visible.
//
namespace ext {
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Waddress"
template <class T, class...Args>
constexpr bool __constructible_object = false;
template <class T, class...Args>
requires requires(Args&&...args) {
T{ (Args&&)args... };
new T{ (Args&&)args... };
}
constexpr bool __constructible_object<T, Args...> = true;

template <class T, class...Args>
concept bool ConstructibleObject =
Destructible<T>() && __constructible_object<T, Args...>;
#pragma GCC diagnostic pop

// 20150718: Not to spec: spec is broken.
// FIXME: Correct wording.
template <class T, class...Args>
concept bool BindableReference =
_Is<T, is_reference> &&
// requires(Args&&...args) { T{ (Args&&)args... }; };
// requires(Args&&...args) { T( (Args&&)args... ); };
_Is<T, is_constructible, Args...>;
// Not to spec
// See https://github.com/ericniebler/stl2/issues/301
template <class T, class... Args>
concept bool Constructible() {
return Destructible<T>() && _Is<T, is_constructible, Args...>;
}

namespace models {
template <class T, class...Args>
constexpr bool ConstructibleObject = false;
__stl2::ext::ConstructibleObject{T, ...Args}
constexpr bool ConstructibleObject<T, Args...> = true;

template <class T, class...Args>
constexpr bool BindableReference = false;
__stl2::ext::BindableReference{T, ...Args}
constexpr bool BindableReference<T, Args...> = true;

template <class T, class...Args>
constexpr bool Constructible =
ConstructibleObject<T, Args...> ||
BindableReference<T, Args...>;
}

template <class T, class...Args>
concept bool Constructible() {
return models::Constructible<T, Args...>;
template <class, class...>
constexpr bool Constructible = false;
__stl2::Constructible{T, ...Args}
constexpr bool Constructible<T, Args...> = 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 <class T>
constexpr bool __default_constructible = false;
template <class T>
requires requires(const std::size_t n) {
new T[n]{}; // not required to be equality preserving
}
constexpr bool __default_constructible<T> = true;

// Not to spec
// https://github.com/ericniebler/stl2/issues/301
template <class T>
concept bool DefaultConstructible() {
return Constructible<T>() && __default_constructible<T>;
return Constructible<T>();
}

namespace models {
Expand Down
3 changes: 2 additions & 1 deletion include/stl2/detail/ebo_box.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ STL2_OPEN_NAMESPACE {
is_class<T>::value && !is_final<T>::value;

template <Destructible T, class Tag = void>
requires _Is<T, is_object>
class ebo_box {
public:
ebo_box() requires DefaultConstructible<T>() = default;
Expand Down Expand Up @@ -54,7 +55,7 @@ STL2_OPEN_NAMESPACE {
};

template <Destructible T, class Tag>
requires __non_final_class<T>
requires _Is<T, is_object> && __non_final_class<T>
class ebo_box<T, Tag> : private T {
public:
using T::T;
Expand Down
1 change: 1 addition & 0 deletions include/stl2/detail/iterator/basic_iterator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@

STL2_OPEN_NAMESPACE {
template <Destructible T>
requires _Is<T, is_object>
class basic_mixin : protected detail::ebo_box<T, basic_mixin<T>> {
using box_t = detail::ebo_box<T, basic_mixin<T>>;
public:
Expand Down
3 changes: 2 additions & 1 deletion include/stl2/detail/semiregular_box.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@

STL2_OPEN_NAMESPACE {
namespace detail {
Destructible{T}
template <Destructible T>
requires _Is<T, is_object>
class semiregular_box {
public:
semiregular_box() = default;
Expand Down
4 changes: 3 additions & 1 deletion include/stl2/detail/temporary_vector.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ STL2_OPEN_NAMESPACE {
};

template <Destructible T>
requires _Is<T, is_object>
class temporary_vector {
T* begin_ = nullptr;
T* end_ = nullptr;
Expand Down Expand Up @@ -159,7 +160,8 @@ STL2_OPEN_NAMESPACE {
{ emplace_back(__stl2::move(t)); }
};

Destructible{T}
template <Destructible T>
requires _Is<T, is_object>
temporary_vector<T> make_temporary_vector(temporary_buffer<T>& buf) {
return {buf};
}
Expand Down
4 changes: 2 additions & 2 deletions include/stl2/optional.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ STL2_OPEN_NAMESPACE {
};

template <class T>
requires models::Destructible<T>
requires models::Destructible<T> && _Is<T, is_object>
class optional;

namespace __optional {
Expand Down Expand Up @@ -233,7 +233,7 @@ STL2_OPEN_NAMESPACE {
}

template <class T>
requires models::Destructible<T>
requires models::Destructible<T> && _Is<T, is_object>
class optional
: public meta::_t<ext::optional_storage<T>>
, detail::smf_control::copy<models::CopyConstructible<T>>
Expand Down
Loading

0 comments on commit c946f3e

Please sign in to comment.