diff --git a/include/boost/intrusive/rbtree_algorithms.hpp b/include/boost/intrusive/rbtree_algorithms.hpp index f333ff6..7714982 100644 --- a/include/boost/intrusive/rbtree_algorithms.hpp +++ b/include/boost/intrusive/rbtree_algorithms.hpp @@ -23,10 +23,6 @@ #ifndef BOOST_INTRUSIVE_RBTREE_ALGORITHMS_HPP #define BOOST_INTRUSIVE_RBTREE_ALGORITHMS_HPP -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - #include #include @@ -37,6 +33,10 @@ #include #include +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + namespace boost { namespace intrusive { @@ -72,8 +72,14 @@ struct rbtree_node_checker typedef ValueTraits value_traits; typedef typename value_traits::node_traits node_traits; typedef typename node_traits::const_node_ptr const_node_ptr; + typedef typename node_traits::node_ptr node_ptr; - typedef typename base_checker_t::return_type return_type; + struct return_type + : public base_checker_t::return_type + { + return_type() : black_count_(0) {} + std::size_t black_count_; + }; rbtree_node_checker(const NodePtrCompare& comp, ExtraChecker extra_checker) : base_checker_t(comp, extra_checker) @@ -83,13 +89,21 @@ struct rbtree_node_checker const return_type& check_return_left, const return_type& check_return_right, return_type& check_return) { - if (node_traits::get_color(p) == node_traits::red()) - { - if (node_traits::get_left(p)) - BOOST_INTRUSIVE_INVARIANT_ASSERT(node_traits::get_color(node_traits::get_left(p)) == node_traits::black()); - if (node_traits::get_right(p)) - BOOST_INTRUSIVE_INVARIANT_ASSERT(node_traits::get_color(node_traits::get_right(p)) == node_traits::black()); + + if (node_traits::get_color(p) == node_traits::red()){ + //Red nodes have black children + const node_ptr p_left(node_traits::get_left(p)); + const node_ptr p_right(node_traits::get_right(p)); + BOOST_INTRUSIVE_INVARIANT_ASSERT(!p_left || node_traits::get_color(p_left) == node_traits::black()); + BOOST_INTRUSIVE_INVARIANT_ASSERT(!p_right || node_traits::get_color(p_right) == node_traits::black()); + //Red node can't be root + BOOST_INTRUSIVE_INVARIANT_ASSERT(node_traits::get_parent(node_traits::get_parent(p)) != p); } + //Every path to p contains the same number of black nodes + const std::size_t l_black_count = check_return_left.black_count_; + BOOST_INTRUSIVE_INVARIANT_ASSERT(l_black_count == check_return_right.black_count_); + check_return.black_count_ = l_black_count + + static_cast(node_traits::get_color(p) == node_traits::black()); base_checker_t::operator()(p, check_return_left, check_return_right, check_return); } };