Skip to content

Commit 853f929

Browse files
Added concepts, cleaned up constraints
1 parent d3566a9 commit 853f929

File tree

1 file changed

+41
-10
lines changed

1 file changed

+41
-10
lines changed

include/queue/wait_queue.hpp

Lines changed: 41 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -112,10 +112,11 @@
112112
*
113113
* The container type must support the following (depending on which
114114
* methods are called): default construction, construction with an initial size,
115-
* @c push_back (preferably overloaded for both copy and move),
115+
* @c push_back (preferably overloaded for both copy and move semantics),
116116
* @c emplace_back (with a template parameter pack), @c front, @c pop_front,
117117
* @c empty, and @c size. The container must also have a @c size_type
118-
* defined.
118+
* defined. Type constraints and concepts are defined for the various
119+
* type requirements.
119120
*
120121
* Iterators on a @c wait_queue are not supported, due to obvious difficulties
121122
* with maintaining consistency and integrity. The @c apply method can be used to
@@ -159,9 +160,39 @@
159160
#include <optional>
160161
#include <utility> // std::move, std::move_if_noexcept
161162
#include <type_traits> // for requires clauses and noexcept specs
163+
#include <concepts>
162164

163165
namespace chops {
164166

167+
// requirements for wait_queue container
168+
169+
template <typename Ctr, typename T>
170+
concept supports_push_back = requires (Ctr ctr, T val) {
171+
ctr.push_back(val);
172+
};
173+
174+
template <typename Ctr, typename ... Args>
175+
concept supports_emplace_back = requires (Ctr ctr, Args args) {
176+
ctr.emplace_back(args);
177+
};
178+
179+
template <typename Ctr>
180+
concept supports_empty = requires (Ctr ctr) {
181+
ctr.empty();
182+
};
183+
184+
template <typename Ctr>
185+
concept supports_pop_front = requires (Ctr ctr) {
186+
ctr.pop_front();
187+
};
188+
189+
template <typename Ctr>
190+
concept supports_size = requires (Ctr ctr) {
191+
ctr.size();
192+
};
193+
194+
// declaration for wait_queue
195+
165196
template <typename T, typename Container = std::deque<T> >
166197
requires std::is_copy_constructible_v<T> || std::is_move_constructible_v<T>
167198
class wait_queue {
@@ -375,7 +406,7 @@ class wait_queue {
375406
*/
376407
auto push(const T& val) /* noexcept(std::is_nothrow_copy_constructible_v<T>) */
377408
-> bool
378-
requires requires (T val, Container c) { c.push_back(val); }
409+
requires supports_push_back<Container, T>
379410

380411
{
381412
if (m_stop_tok.stop_requested()) {
@@ -399,7 +430,7 @@ class wait_queue {
399430
*/
400431
auto push(T&& val) /* noexcept(std::is_nothrow_move_constructible_v<T>) */
401432
-> bool
402-
requires requires (T val, Container c) { c.push_back(val); }
433+
requires supports_push_back<Container, T>
403434

404435
{
405436
if (m_stop_tok.stop_requested()) {
@@ -431,7 +462,7 @@ class wait_queue {
431462
template <typename ... Args>
432463
auto emplace_push(Args &&... args) /* noexcept(std::is_nothrow_constructible_v<T, Args...>)*/
433464
-> bool
434-
// requires requires (Container c) { c.emplace_back(); }
465+
requires supports_emplace_back<Container, Args...>
435466

436467
{
437468
if (m_stop_tok.stop_requested()) {
@@ -459,7 +490,7 @@ class wait_queue {
459490
*/
460491
[[nodiscard]] auto wait_and_pop() /* noexcept(std::is_nothrow_constructible_v<T>) */
461492
-> std::optional<T>
462-
requires requires (Container c) { c.empty(); c.pop_front(); }
493+
requires supports_empty<Container> && supports_pop_front<Container>
463494

464495
{
465496
std::unique_lock<std::mutex> lk{m_mut};
@@ -490,7 +521,7 @@ class wait_queue {
490521
*/
491522
[[nodiscard]] auto try_pop() /* noexcept(std::is_nothrow_constructible_v<T>) */
492523
-> std::optional<T>
493-
requires requires (Container c) { c.empty(); c.pop_front(); }
524+
requires supports_empty<Container> && supports_pop_front<Container>
494525
{
495526
if (m_stop_tok.stop_requested()) {
496527
return std::optional<T> {};
@@ -539,7 +570,7 @@ class wait_queue {
539570
template <typename F>
540571
auto apply(F&& func) const /* noexcept(std::is_nothrow_invocable_v<F&&, const T&>) */
541572
-> void
542-
requires requires (T elem, F func) { func(elem); }
573+
requires std::is_invocable_v<F, T>
543574

544575
{
545576
lock_guard lk{m_mut};
@@ -569,7 +600,7 @@ class wait_queue {
569600
*/
570601
[[nodiscard]] auto empty() const /* noexcept */
571602
-> bool
572-
requires requires (Container c) { c.empty(); }
603+
requires supports_empty<Container>
573604

574605
{
575606
lock_guard lk{m_mut};
@@ -584,7 +615,7 @@ class wait_queue {
584615
*/
585616
[[nodiscard]] auto size() const /* noexcept */
586617
-> size_type
587-
requires requires (Container c) { c.size(); }
618+
requires supports_size<Container>
588619

589620
{
590621
lock_guard lk{m_mut};

0 commit comments

Comments
 (0)