diff --git a/xo-indentlog/include/xo/indentlog/timeutil/timeutil.hpp b/xo-indentlog/include/xo/indentlog/timeutil/timeutil.hpp index 1a2a0240..53a70f6c 100644 --- a/xo-indentlog/include/xo/indentlog/timeutil/timeutil.hpp +++ b/xo-indentlog/include/xo/indentlog/timeutil/timeutil.hpp @@ -8,6 +8,7 @@ # include #endif #include +#include #include #include diff --git a/xo-ordinaltree/include/xo/ordinaltree/RedBlackTree.hpp b/xo-ordinaltree/include/xo/ordinaltree/RedBlackTree.hpp index 9683f487..f052e482 100644 --- a/xo-ordinaltree/include/xo/ordinaltree/RedBlackTree.hpp +++ b/xo-ordinaltree/include/xo/ordinaltree/RedBlackTree.hpp @@ -62,7 +62,7 @@ namespace xo { class RedBlackTree : public xo::gc::gc_allocator_traits::object_interface_type { static_assert(ordered_key); static_assert(std::default_initializable); - static_assert(std::predicate); + //static_assert(three_way_comparator); // std::less doesn't deliver this static_assert(valid_rbtree_reduce_functor); public: @@ -373,7 +373,8 @@ namespace xo { //scope log(XO_DEBUG(true), tag("variant", "autoinsert"), tag("key", k)); std::pair insert_result - = RbUtil::template insert_aux(this->node_alloc_, + = RbUtil::template insert_aux(this->compare_, + this->node_alloc_, value_type(k, Value() /*used iff creating new node*/), false /*allow_replace_flag*/, this->reduce_fn_, @@ -512,7 +513,8 @@ namespace xo { RbNode * adj_root = this->root_; std::pair insert_result - = RbUtil::insert_aux(this->node_alloc_, + = RbUtil::insert_aux(this->compare_, + this->node_alloc_, std::move(kv_pair), true /*allow_replace_flag*/, this->reduce_fn_, diff --git a/xo-ordinaltree/include/xo/ordinaltree/rbtree/RbTreeUtil.hpp b/xo-ordinaltree/include/xo/ordinaltree/rbtree/RbTreeUtil.hpp index 6c073f4b..d7d2ab76 100644 --- a/xo-ordinaltree/include/xo/ordinaltree/rbtree/RbTreeUtil.hpp +++ b/xo-ordinaltree/include/xo/ordinaltree/rbtree/RbTreeUtil.hpp @@ -788,7 +788,8 @@ namespace xo { */ template static std::pair - insert_aux(NodeAllocator & alloc, + insert_aux(Compare const & key_cmp, + NodeAllocator & alloc, value_type const & kv_pair, bool allow_replace_flag, Reduce const & reduce_fn, @@ -804,7 +805,9 @@ namespace xo { Direction d = D_Invalid; while (N) { - if (kv_pair.first == N->key()) { + auto cmp = key_cmp(kv_pair.first, N->key()); + + if (cmp == 0) { // kv_pair.first == N->key()) { if(allow_replace_flag) { /* match on this key already present in tree * -> just update assoc'd value @@ -825,7 +828,7 @@ namespace xo { return std::make_pair(false, N); } - d = ((kv_pair.first < N->key()) ? D_Left : D_Right); + d = (cmp < 0 /*(kv_pair.first < N->key())*/ ? D_Left : D_Right); /* insert into left subtree somewhere */ RbNode * C = N->child(d); diff --git a/xo-ordinaltree/include/xo/ordinaltree/rbtree/RbTypes.hpp b/xo-ordinaltree/include/xo/ordinaltree/rbtree/RbTypes.hpp index 0e3b3db1..5579048f 100644 --- a/xo-ordinaltree/include/xo/ordinaltree/rbtree/RbTypes.hpp +++ b/xo-ordinaltree/include/xo/ordinaltree/rbtree/RbTypes.hpp @@ -6,22 +6,44 @@ #pragma once #include "NullReduce.hpp" +#include namespace xo { namespace tree { - /* red-black tree with order statistics + /** + * Wrapper to workaround concept requirements that prevent + * std::compare_three_way working with const references + **/ + struct DefaultThreeWayCompare { +#ifdef NOT_YET // not working with clang 16.0.6 + template + auto operator()(const T & a, const T & b) const { + return a <=> b; + } +#endif + + template + auto operator()(const T& a, const T& b) const -> std::strong_ordering { + if (a < b) return std::strong_ordering::less; + if (b < a) return std::strong_ordering::greater; + return std::strong_ordering::equal; + } + }; + + /** + * Red-black tree with order statistics * - * require: + * Require: * - Key is equality comparable * - Key, Value, Reduce are copyable and null-constructible * - Reduce.value_type = Accumulator * - Reduce.operator() :: (Accumulator x Key) -> Accumulator * - Reduce.operator() :: (Accumulator x Accumulator) -> Accumulator - */ + **/ template , - typename Compare = std::less, + typename Compare = DefaultThreeWayCompare, //std::compare_three_way, //std::less, typename Allocator = std::allocator>> class RedBlackTree; @@ -87,6 +109,16 @@ namespace xo { && std::default_initializable && std::totally_ordered); + + template + concept three_way_comparator = requires(const Compare& comp, + const Key& a, + const Key& b) + { + { comp(a, b) } -> std::same_as; + }; + template concept valid_rbtree_node_value = (std::copyable && std::default_initializable); diff --git a/xo-ordinaltree/utest/RedBlackTree-gc.test.cpp b/xo-ordinaltree/utest/RedBlackTree-gc.test.cpp index cf716eb9..9de4a50f 100644 --- a/xo-ordinaltree/utest/RedBlackTree-gc.test.cpp +++ b/xo-ordinaltree/utest/RedBlackTree-gc.test.cpp @@ -56,7 +56,7 @@ namespace xo { using RbTree = RedBlackTree, - std::less, + std::compare_three_way, xo::gc::allocator>>; constexpr bool c_debug_flag = false; @@ -125,7 +125,7 @@ namespace xo { using RbTree = RedBlackTree, - std::less, + std::compare_three_way, //std::less, xo::gc::allocator>>; constexpr bool c_debug_flag = false;