xo-ordinaltree: 3-way comparison scaffolding. wip

This commit is contained in:
Roland Conybeare 2025-12-06 10:56:10 -05:00
commit 1d3999a6bd
5 changed files with 50 additions and 12 deletions

View file

@ -8,6 +8,7 @@
# include <format>
#endif
#include <chrono>
#include <compare>
#include <cstdint>
#include <time.h>

View file

@ -62,7 +62,7 @@ namespace xo {
class RedBlackTree : public xo::gc::gc_allocator_traits<Allocator>::object_interface_type {
static_assert(ordered_key<Key>);
static_assert(std::default_initializable<Compare>);
static_assert(std::predicate<Compare, Key, Key>);
//static_assert(three_way_comparator<Compare, Key>); // std::less doesn't deliver this
static_assert(valid_rbtree_reduce_functor<Reduce, Value>);
public:
@ -373,7 +373,8 @@ namespace xo {
//scope log(XO_DEBUG(true), tag("variant", "autoinsert"), tag("key", k));
std::pair<bool, RbNode *> insert_result
= RbUtil::template insert_aux<node_allocator_type>(this->node_alloc_,
= RbUtil::template insert_aux<node_allocator_type>(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<bool, RbNode *> 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_,

View file

@ -788,7 +788,8 @@ namespace xo {
*/
template <typename NodeAllocator>
static std::pair<bool, RbNode *>
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);

View file

@ -6,22 +6,44 @@
#pragma once
#include "NullReduce.hpp"
#include <compare>
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 <typename T>
auto operator()(const T & a, const T & b) const {
return a <=> b;
}
#endif
template <typename T>
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 Key,
typename Value,
typename Reduce = NullReduce<Key>,
typename Compare = std::less<Key>,
typename Compare = DefaultThreeWayCompare, //std::compare_three_way, //std::less<Key>,
typename Allocator = std::allocator<std::pair<const Key, Value>>>
class RedBlackTree;
@ -87,6 +109,16 @@ namespace xo {
&& std::default_initializable<Key>
&& std::totally_ordered<Key>);
template <typename Compare,
typename Key>
concept three_way_comparator = requires(const Compare& comp,
const Key& a,
const Key& b)
{
{ comp(a, b) } -> std::same_as<std::strong_ordering>;
};
template <typename Value>
concept valid_rbtree_node_value = (std::copyable<Value>
&& std::default_initializable<Value>);

View file

@ -56,7 +56,7 @@ namespace xo {
using RbTree = RedBlackTree<int,
double,
SumReduce<double>,
std::less<int>,
std::compare_three_way,
xo::gc::allocator<std::pair<const int, double>>>;
constexpr bool c_debug_flag = false;
@ -125,7 +125,7 @@ namespace xo {
using RbTree = RedBlackTree<int,
double,
SumReduce<double>,
std::less<int>,
std::compare_three_way, //std::less<int>,
xo::gc::allocator<std::pair<const int, double>>>;
constexpr bool c_debug_flag = false;