Использование шаблона для вложенного класса в C ++ - PullRequest
0 голосов
/ 08 апреля 2020

В следующем фрагменте кода у меня есть сомнение и ошибка, которую я не могу устранить:

  1. При определении функции root() снаружи class BST, почему Я должен использовать typename bst::Node*? Если бы BST не было шаблонов, я мог бы использовать только BST::Node верно?

  2. При перегрузке operator<< для BST вне класса выдается следующая ошибка:

Неопределенные символы для архитектуры x86_64: «оператор << (std :: __ 1 :: basic_ostream> &, BST :: Node *)», на который ссылается: BST :: inorderTreeWalk (BST :: Node *) в bst_raw. cpp .o ld: символ (ы) не найден для архитектуры x86_64

Может кто-нибудь помочь помочь прояснить мои сомнения?

#define T template <typename K, typename V>
#define bst BST<K,V>

T
class BST {
public:
    class Node;
private:
    Node* _root;
public:
    BST():_root(NULL) {};
    bool empty() ;
    Node* root();
    void set_root(Node* z);
    void insert(K key, V value);
    void inorderTreeWalk(Node* x);
};
T
class bst::Node {
public:
    Node(K k, V v) : _key(k), _val(v) {};
    K key() const { return _key; }
    V val() const { return _val; }
    Node* left() { return l;}
    void set_left(Node* n) { l = n;}
    Node* right() { return r;}
    void set_right(Node* n) { r = n; }
    Node* parent();
    void set_parent(Node* n) { p = n; }

    friend ostream &operator<< (ostream &os, Node* x);
private:
    Node *l, *r, *p;
    K _key;
    V _val;
};

T
typename bst::Node* bst::root() { return _root; }  // why typename?

T
ostream &operator<<(ostream &os, typename bst::Node& x) {
    os << x.key();
    return os;
} // runs into an error

1 Ответ

1 голос
/ 08 апреля 2020

Да, это называется поиском зависимого имени.

Если C является шаблоном, то в конструкции C<T>::N N может быть именем типа или stati c член класса. Компилятор не может знать, что именно, не зная типа T. Это потому, что C может быть специализированным, так что N имеет разные значения в зависимости от типа T.

Когда компилятор впервые видит template <typename K, typename V> typename BST<K,V>::Node* bst<K,V>::root(), он не знает, какие типы K и V, поэтому нужно сказать, что Node является типом для анализа кода. Вот что делает третий typename.

...