-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add concept for standard container requirements (#314)
* Add concept for standard container requirements * Archtypes for container and allocator aware types, with tests. * std::vector<bool> sepcialisation of get_allocator is not noexcept * Support sequence containers * Remove duplication * Include ranges * Correct namespace * Update archtype for from_range * Range methods fix * Patch up the sequence concept as best we can * Contiguous concept with tests * Concept for reversible container requirements and partial concepts for associativ and unordered * Complete associative concept * Try compound requirement for visual studio * Complete unorder container concepts * Check for all basic string instantiations
- Loading branch information
Showing
42 changed files
with
1,318 additions
and
12 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
add_subdirectory(concepts) |
12 changes: 12 additions & 0 deletions
12
libraries/core/src/morpheus/core/containers/concepts/CMakeLists.txt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
add_subdirectory(detail) | ||
|
||
target_sources(MorpheusCore | ||
PUBLIC | ||
allocator_aware.hpp | ||
associative.hpp | ||
container.hpp | ||
contiguous.hpp | ||
reversible.hpp | ||
sequence.hpp | ||
unordered.hpp | ||
) |
29 changes: 29 additions & 0 deletions
29
libraries/core/src/morpheus/core/containers/concepts/allocator_aware.hpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
#pragma once | ||
|
||
#include "morpheus/core/containers/concepts/container.hpp" | ||
|
||
#include <concepts> | ||
#include <utility> | ||
|
||
namespace morpheus::containers::concepts | ||
{ | ||
|
||
/// \concept AllocatorAware | ||
/// Concept capturing the requirements for an allocator aware container as outline in the standard at | ||
/// <a href="https://eel.is/c++draft/container.alloc.reqmts">[container.alloc.reqmts]</a>, details at | ||
/// <a href="https://en.cppreference.com/w/cpp/named_req/AllocatorAwareContainer">AllocatorAwareContainer</a>. | ||
template <typename X> | ||
concept AllocatorAware = Container<X> && requires(X x, X&& rx, typename X::allocator_type a){ | ||
requires std::same_as<typename X::allocator_type::value_type, typename X::value_type>; | ||
requires std::default_initializable<X>; | ||
{ X(a) }; | ||
{ X(std::as_const(x), a) }; | ||
{ X(std::move(rx)) }; | ||
{ X(std::move(rx), a) }; | ||
{ std::as_const(x).get_allocator() } -> std::same_as<typename X::allocator_type>; | ||
{ x = x } -> std::same_as<X&>; | ||
{ x = rx } -> std::same_as<X&>; | ||
{ x.swap(x) } -> std::same_as<void>; | ||
}; | ||
|
||
} // namespace morpheus::containers::concepts |
66 changes: 66 additions & 0 deletions
66
libraries/core/src/morpheus/core/containers/concepts/associative.hpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
#pragma once | ||
|
||
#include "morpheus/core/containers/concepts/detail/return_types.hpp" | ||
#include "morpheus/core/containers/concepts/allocator_aware.hpp" | ||
|
||
#include <concepts> | ||
#include <initializer_list> | ||
|
||
namespace morpheus::containers::concepts | ||
{ | ||
|
||
/// \concept Associative | ||
/// Concept capturing the requirements for an associative container as outline in the standard at | ||
/// <a href="https://eel.is/c++draft/container.requirements#associative.reqmts">[associative.reqmts]</a>, details at | ||
/// <a href="https://en.cppreference.com/w/cpp/named_req/AssociativeContainer">AssociativeContainer</a>. | ||
template <typename T> | ||
concept Associative = AllocatorAware<T> && requires(T t, typename T::value_type v, typename T::key_type k, typename T::size_type s, typename T::iterator i, | ||
typename T::const_iterator ci, typename T::key_compare c, typename T::node_type n, | ||
std::initializer_list<typename T::value_type> il) | ||
{ | ||
requires (std::default_initializable<typename T::key_compare>) and (std::copy_constructible<typename T::key_compare>); | ||
{ T(c) }; | ||
{ T(i, i, c) }; | ||
{ T(i, i) }; | ||
#if (__cpp_lib_containers_ranges >= 202202L) | ||
{ T(std::from_range, ranges::subrange<typename T::iterator>{}, c) }; | ||
{ T(std::from_range, ranges::subrange<typename T::iterator>{}) }; | ||
#endif // (__cpp_lib_containers_ranges >= 202202L) | ||
{ T(il, c) }; | ||
{ T(il) }; | ||
{ t = il }; | ||
{ std::as_const(t).key_comp() } -> std::same_as<typename T::key_compare>; | ||
{ std::as_const(t).value_comp() } -> std::same_as<typename T::value_compare>; | ||
{ t.emplace() } -> detail::InsertReturnType<T>; | ||
{ t.emplace_hint(i) } -> std::same_as<typename T::iterator>; | ||
{ t.insert(v) } -> detail::InsertReturnType<T>; | ||
{ t.insert(ci, v) } -> std::same_as<typename T::iterator>; | ||
{ t.insert(i, i) } -> std::same_as<void>; | ||
#if (__cpp_lib_containers_ranges >= 202202L) | ||
{ t.insert_range(ranges::subrange<typename T::iterator>{}) } -> std::same_as<void>; | ||
#endif // (__cpp_lib_containers_ranges >= 202202L) | ||
{ t.insert(il) } -> std::same_as<void>; | ||
{ t.insert(std::move(n)) } -> detail::InsertNodeHandleReturnType<T>; | ||
{ t.insert(ci, std::move(n)) } -> std::same_as<typename T::iterator>; | ||
{ t.extract(k) } -> std::same_as<typename T::node_type>; | ||
{ t.extract(ci) } -> std::same_as<typename T::node_type>; | ||
{ t.merge(t) } -> std::same_as<void>; | ||
{ t.erase(i) } -> std::same_as<typename T::iterator>; | ||
{ t.erase(ci) } -> std::same_as<typename T::iterator>; | ||
{ t.erase(i, i) } -> std::same_as<typename T::iterator>; | ||
{ t.erase(ci, ci) } -> std::same_as<typename T::iterator>; | ||
{ t.erase(k) } -> std::same_as<typename T::size_type>; | ||
{ t.clear() } -> std::same_as<void>; | ||
{ t.find(k) } -> std::same_as<typename T::iterator>; | ||
{ std::as_const(t).find(k) } -> std::same_as<typename T::const_iterator>; | ||
{ std::as_const(t).count(k) } -> std::same_as<typename T::size_type>; | ||
{ std::as_const(t).contains(k) } -> std::same_as<bool>; | ||
{ t.lower_bound(k) } -> detail::BoundReturnType<T>; | ||
{ std::as_const(t).lower_bound(k) } -> detail::BoundConstReturnType<T>; | ||
{ t.equal_range(k) } -> detail::BoundReturnType<T>; | ||
{ std::as_const(t).equal_range(k) } -> detail::BoundConstReturnType<T>; | ||
{ t.upper_bound(k) } -> detail::BoundReturnType<T>; | ||
{ std::as_const(t).upper_bound(k) } -> detail::BoundConstReturnType<T>; | ||
}; | ||
|
||
} // namespace morpheus::containers::concepts |
34 changes: 34 additions & 0 deletions
34
libraries/core/src/morpheus/core/containers/concepts/container.hpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
#pragma once | ||
|
||
#include <concepts> | ||
#include <iterator> | ||
#include <utility> | ||
|
||
namespace morpheus::containers::concepts | ||
{ | ||
|
||
/// \concept Container | ||
/// Concept capturing the requirements for a container as outline in the standard at | ||
/// <a href="https://eel.is/c++draft/container.requirements">[container.requirements]</a>, details at | ||
/// <a href="https://en.cppreference.com/w/cpp/named_req/Container">Container</a>. | ||
template<typename C> | ||
concept Container = requires(C c) { | ||
typename C::value_type; | ||
typename C::reference; | ||
typename C::const_reference; | ||
requires std::forward_iterator<typename C::iterator>; | ||
requires std::forward_iterator<typename C::const_iterator>; | ||
requires std::signed_integral<typename C::difference_type>; | ||
requires std::unsigned_integral<typename C::size_type>; | ||
requires std::convertible_to<typename C::iterator, typename C::const_iterator>; | ||
requires std::regular<C>; | ||
{ begin(c) } -> std::same_as<typename C::iterator>; | ||
{ end(c) } -> std::same_as<typename C::iterator>; | ||
{ cbegin(std::as_const(c)) } -> std::same_as<typename C::const_iterator>; | ||
{ cend(std::as_const(c)) } -> std::same_as<typename C::const_iterator>; | ||
requires (not std::bidirectional_iterator<typename C::iterator>) or requires {{ size(c) } -> std::same_as<typename C::size_type>; }; | ||
{ c.max_size() } -> std::same_as<typename C::size_type>; | ||
{ empty(c) } -> std::same_as<bool>; | ||
}; | ||
|
||
} // namespace morpheus::containers::concepts |
21 changes: 21 additions & 0 deletions
21
libraries/core/src/morpheus/core/containers/concepts/contiguous.hpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
#pragma once | ||
|
||
#include "morpheus/core/containers/concepts/sequence.hpp" | ||
|
||
#include <concepts> | ||
#include <iterator> | ||
|
||
namespace morpheus::containers::concepts | ||
{ | ||
|
||
/// \concept Contiguous | ||
/// Concept capturing the requirements for a contiguous container, a named requirement outlined in the standard at | ||
/// <a href="https://eel.is/c++draft/container.requirements.general">[container.requirements.general]</a>, details at | ||
/// <a href="https://en.cppreference.com/w/cpp/named_req/ContiguousContainer">ContiguousContainer</a>. | ||
template <typename T> | ||
concept Contiguous = StrictSequence<T> && requires(T t){ | ||
requires std::contiguous_iterator<typename T::iterator>; | ||
requires std::contiguous_iterator<typename T::const_iterator>; | ||
}; | ||
|
||
} // namespace morpheus::containers::concepts |
4 changes: 4 additions & 0 deletions
4
libraries/core/src/morpheus/core/containers/concepts/detail/CMakeLists.txt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
target_sources(MorpheusCore | ||
PUBLIC | ||
return_types.hpp | ||
) |
33 changes: 33 additions & 0 deletions
33
libraries/core/src/morpheus/core/containers/concepts/detail/return_types.hpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
#pragma once | ||
|
||
#include <concepts> | ||
#include <utility> | ||
|
||
namespace morpheus::containers::concepts::detail | ||
{ | ||
|
||
template <typename I, typename T> | ||
concept InsertReturnType = requires | ||
{ | ||
requires std::same_as<I, typename T::iterator> or std::same_as<I, std::pair<typename T::iterator, bool>>; | ||
}; | ||
|
||
template <typename I, typename T> | ||
concept InsertNodeHandleReturnType = requires | ||
{ | ||
requires requires { std::same_as<I, typename T::iterator>; } or requires { std::same_as<I, typename T::insert_return_type>; }; | ||
}; | ||
|
||
template <typename I, typename T> | ||
concept BoundReturnType = requires | ||
{ | ||
requires std::same_as<I, typename T::iterator> or std::same_as<I, std::pair<typename T::iterator, typename T::iterator>>; | ||
}; | ||
|
||
template <typename I, typename T> | ||
concept BoundConstReturnType = requires | ||
{ | ||
requires std::same_as<I, typename T::const_iterator> or std::same_as<I, std::pair<typename T::const_iterator, typename T::const_iterator>>; | ||
}; | ||
|
||
} // namespace morpheus::containers::concepts |
28 changes: 28 additions & 0 deletions
28
libraries/core/src/morpheus/core/containers/concepts/reversible.hpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
#pragma once | ||
|
||
#include "morpheus/core/containers/concepts/container.hpp" | ||
|
||
#include <concepts> | ||
#include <iterator> | ||
#include <utility> | ||
|
||
namespace morpheus::containers::concepts | ||
{ | ||
|
||
/// \concept Reversible | ||
/// Concept capturing the requirements for a reversible container, a named requirement outlined in the standard at | ||
/// <a href="https://eel.is/c++draft/container.rev.reqmts">[container.rev.reqmts]</a>, details at | ||
/// <a href="https://en.cppreference.com/w/cpp/named_req/ReversibleContainer">ReversibleContainer</a>. | ||
template <typename T> | ||
concept Reversible = Container<T> && requires(T t){ | ||
typename T::reverse_iterator; | ||
typename T::const_reverse_iterator; | ||
requires std::same_as<typename T::reverse_iterator, std::reverse_iterator<typename T::iterator>>; | ||
requires std::same_as<typename T::const_reverse_iterator, std::reverse_iterator<typename T::const_iterator>>; | ||
{ rbegin(t) } -> std::same_as<typename T::reverse_iterator>; | ||
{ rend(t) } -> std::same_as<typename T::reverse_iterator>; | ||
{ crbegin(std::as_const(t)) } -> std::same_as<typename T::const_reverse_iterator>; | ||
{ crend(std::as_const(t)) } -> std::same_as<typename T::const_reverse_iterator>; | ||
}; | ||
|
||
} // namespace morpheus::containers::concepts |
67 changes: 67 additions & 0 deletions
67
libraries/core/src/morpheus/core/containers/concepts/sequence.hpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
#pragma once | ||
|
||
#include "morpheus/core/containers/concepts/container.hpp" | ||
#include "morpheus/core/conformance/ranges.hpp" | ||
#include "morpheus/core/meta/is_array.hpp" | ||
#include "morpheus/core/meta/is_string.hpp" | ||
|
||
#include <concepts> | ||
#include <initializer_list> | ||
#include <forward_list> | ||
#include <string> | ||
#include <version> | ||
|
||
namespace morpheus::containers::concepts | ||
{ | ||
|
||
/// \concept Sequence | ||
/// Concept capturing the requirements for a sequence container as outline in the standard at | ||
/// <a href="https://eel.is/c++draft/sequence.reqmts">[sequence.requirements]</a>, details at | ||
/// <a href="https://en.cppreference.com/w/cpp/named_req/SequenceContainer">SequenceContainer</a>. | ||
template <typename T> | ||
concept Sequence = Container<T> && requires(T t, typename T::value_type v, typename T::size_type s, typename T::iterator i, std::initializer_list<typename T::value_type> il){ | ||
{ T(s, v) }; | ||
{ T(i, i) }; | ||
#if (__cpp_lib_containers_ranges >= 202202L) | ||
{ T(std::from_range, ranges::subrange<typename T::iterator>{}) }; | ||
#endif // (__cpp_lib_containers_ranges >= 202202L) | ||
{ T(il) }; | ||
{ t = il }; | ||
{ t.insert(i, v) } -> std::same_as<typename T::iterator>; | ||
{ t.insert(i, std::move(v)) } -> std::same_as<typename T::iterator>; | ||
{ t.insert(i, s, v) } -> std::same_as<typename T::iterator>; | ||
{ t.insert(i, i, i) } -> std::same_as<typename T::iterator>; | ||
#if (__cpp_lib_containers_ranges >= 202202L) | ||
{ t.insert_range(i, ranges::subrange<typename T::iterator>{}) } -> std::same_as<typename T::iterator>; | ||
#endif // (__cpp_lib_containers_ranges >= 202202L) | ||
{ t.insert(i, il) } -> std::same_as<typename T::iterator>; | ||
{ t.erase(i) } -> std::same_as<typename T::iterator>; | ||
{ t.erase(i, i) } -> std::same_as<typename T::iterator>; | ||
{ t.clear() } -> std::same_as<void>; | ||
{ t.assign(i, i) } -> std::same_as<void>; | ||
#if (__cpp_lib_containers_ranges >= 202202L) | ||
{ t.assign_range(ranges::subrange<typename T::iterator>{}) } -> std::same_as<void>; | ||
#endif // (__cpp_lib_containers_ranges >= 202202L) | ||
{ t.assign(il) } -> std::same_as<void>; | ||
{ t.assign(s, v) } -> std::same_as<void>; | ||
}; | ||
|
||
/// \concept StrictSequence | ||
/// Concept strictly capturing the requirements for a sequence container as outline in the standard at | ||
/// <a href="https://eel.is/c++draft/sequence.reqmts">[sequence.requirements]</a>, details at | ||
/// <a href="https://en.cppreference.com/w/cpp/named_req/SequenceContainer">SequenceContainer</a>. | ||
/// The requirements <a href="https://eel.is/c++draft/sequence.reqmts">[sequence.requirements]</a> don't | ||
/// actually match numerous types listed as sequence containers. This includes: | ||
/// - std::string | ||
/// - std::forward_list | ||
/// - std::array | ||
/// Hoever they are listed as as Sequence types while having interfaces that differ from the Sequence | ||
/// container requirements so this extension concept exactly mirrors that requirement. | ||
template <typename T> | ||
concept StrictSequence = meta::is_array_v<T> || | ||
meta::is_string_v<T> || | ||
std::same_as<T, std::forward_list<typename T::value_type>> || | ||
Sequence<T>; | ||
|
||
|
||
} // namespace morpheus::containers::concepts |
Oops, something went wrong.