Static class variable in template class considered template

147 Views Asked by At

I have a static variable, nil, which acts as a sentinel for template <typename Node> Tree. I am augmenting my trees by specializing on the Node type. However, I'm having trouble constructing the nils.

Nil as static member of Tree

Inside tree.h

template <typename Node>
class Tree {
    using NP = Node*;
    using T = typename Node::key_type;

    NP root {nil};
    // nil sentinel
    static NP nil;

    // core utilities
    const static NP get_nil() {
        return nil;
    }
};

enum class Color : char {BLACK = 0, RED = 1};

template <typename T>
struct Basic_node {
        using key_type = T;
        T key;
        Basic_node *parent, *left, *right;
        Color color;
        Basic_node() : color{Color::BLACK} {}   // sentinel construction
        Basic_node(T val, Color col = Color::RED) : 
            key{val}, 
            parent{Tree<Basic_node>::get_nil()}, 
            left{Tree<Basic_node>::get_nil()}, 
            right{Tree<Basic_node>::get_nil()}, 
            color{col} {}
};

template <typename T>
using Basic_tree = Tree<Basic_node<T>>;

template <typename T>
typename Basic_tree<T>::NP Basic_tree<T>::nil {new Basic_node<T>};
// alternatively
template <typename T>
Basic_node<T>* Basic_tree<T>::nil {new Basic_node{}};

The error template definition of non-template 'typename sal::Basic_tree<T>::NP sal::Tree<sal::Basic_node<T> >::nil' occurs in the last two lines.

I want the same nil to be used for all trees using Basic_node with every T type.

Nil as static member of Node

I then tried making nil a static member of Basic_node. This way the nodes don't depend on the tree (that parent{Tree<Basic_node>::get_nil()} is really nasty) and is more natural.

template <typename T>
struct Basic_node {
        static Basic_node* nil;

        using key_type = T;
        T key;
        Basic_node *parent, *left, *right;
        Color color;
        Basic_node() : color{Color::BLACK} {}   // sentinel construction
        Basic_node(T val, Color col = Color::RED) : key{val}, parent{nil}, left{nil}, right{nil}, color{col} {}
};
template <typename T>
Basic_node<T>* Basic_node<T>::nil {new Basic_node{}};

// inside Tree
using Node::nil;

The new error is type 'sal::Basic_node<int>' is not a base type for type 'sal::Tree<sal::Basic_node<int> >' meaning I'm abusing using as it assumes I'm referring to a hierarchy. What I want to mean here is to use Node::nil when I refer to nil in the rest of Tree.

(Note that my last approach worked, it's just that I have to refer to Node::nil every time; also, I'm curious if there's any extra indirection introduced by Node::nil).

0

There are 0 best solutions below