I defined a red-black tree node (with template):
struct rb_node {
    rb_node   *left;
    rb_node   *right;
    rb_node   *parent;
    value_type val;
    enum _Node_color { Black, Red } color;
};
Obviously, I can't create a sentinel node for the Test class, for example:
class Test {
private:
    int v;
public:
    explicit Test(int x) : v(x) {}
    bool operator<(const Test & t) const noexcept { return t.V() > v; }
    int V() const noexcept { return v; }
};
// ... In rb_node<Test>:
static const rb_node sentinel_node; // Wrong!
How to fix this problem without changing Test? --- I found that MSVC STL also uses sentinel nodes, but they solved this problem. How did they do it?
// In <xtree>
    
template <class _Value_type, class _Voidptr>
struct _Tree_node {
    using _Nodeptr   = _Rebind_pointer_t<_Voidptr, _Tree_node>;
    using value_type = _Value_type;
    _Nodeptr _Left; // left subtree, or smallest element if head
    _Nodeptr _Parent; // parent, or root of tree if head
    _Nodeptr _Right; // right subtree, or largest element if head
    char _Color; // _Red or _Black, _Black if head
    char _Isnil; // true only if head (also nil) node; TRANSITION, should be bool
    value_type _Myval = // the stored value, unused if head
        _Returns_exactly<value_type>(); // fake a viable constructor to workaround GH-2749
}
// ...
    void _Alloc_sentinel_and_proxy() {
        const auto _Scary = _Get_scary();
        auto&& _Alproxy   = _GET_PROXY_ALLOCATOR(_Alnode, _Getal());
        _Container_proxy_ptr<_Alnode> _Proxy(_Alproxy, *_Scary);
        _Scary->_Myhead = _Node::_Buyheadnode(_Getal());
        _Proxy._Release();
    }
 
    