C++ ошибка dependent name is not a type, prefix with 'typename' to indicate a type

208
26 июля 2018, 03:20

пишу бинарное дерево и наткнулся на очень непонятную мне ошибку, вот пример:

template<typename T>
class BinaryTree 
{
public:
    ...
private:
    ...
    struct Node
    {
        T value;
        Node* leftChild;
        Node* rightChild;
    };
    Node* copyTree(Node* node);
    ...
};
template<typename T>
BinaryTree<T>::Node* BinaryTree<T>::copyTree(Node* node)
{
    if (node == nullptr) 
    {   
        return nullptr;
    }
    Node* newNode = new Node;
    newNode->value = node->value;
    newNode->leftChild = copyTree(node->leftChild);
    newNode->rightChild = copyTree(node->rightChild);
    return newNode;
}

warning C4346: 'Node': dependent name is not a type
note: prefix with 'typename' to indicate a type
error C2061: syntax error: identifier 'Node'
error C2143: syntax error: missing ';' before '{'
error C2447: '{': missing function header (old-style formal list?)
Answer 1

При использовании квалифицированного имени вложенного типа (т.е. имени вида T::U), когда наружный тип является зависимым (т.е. является шаблоном с неизвестным параметром), требуется указание ключевого слова typename.

В вашем случае: правильно не BinaryTree<T>::Node, а typename BinaryTree<T>::Node.

(Еще раз: это относится только к случаям, когда T - это параметр шаблона. Если же вы указываете конкретный аргумент, то typename добавлять не нужно. Например, BinaryTree<int>::Node.)

В данном примере важно то, что при определении функции-члена класса за пределами класса с использованием классического синтаксиса, тип возвращаемого значения ищется во внешней области видимости, а объявления параметров методов - сначала в области видимости класса. Поэтому при указании типа возвращаемого значения вы вынуждены использовать квалифицированное имя BinaryTree<T>::Node и, согласно правилу выше, добавлять typename. А вот в параметрах функции-члена класса можно свободно использовать неквалифицированное имя Node. То есть правильно

template <typename T>
typename BinaryTree<T>::Node* BinaryTree<T>::copyTree(Node* node)

Если же вам вдруг по какой-то причине захочется и в объявлениях параметров использовать квалифицированные имена типов, то и там будет применяться правило typename

template <typename T>
typename BinaryTree<T>::Node* BinaryTree<T>::copyTree(typename BinaryTree<T>::Node* node)

При использовании нового синтаксиса с auto и замыкающим типом возвращаемого значения, имя типа возвращаемого значения тоже сначала ищется в области видимости класса. Поэтому альтернативным вариантом будет

template <typename T>
auto BinaryTree<T>::copyTree(Node* node) -> Node*

т.е. в этом случае мы обходимся без квалифицированных имен для Node и, соответственно, без typename.

READ ALSO
Вывод кол-во раз char * какой-то int

Вывод кол-во раз char * какой-то int

Пытаюсь сделать следующие,

203
Qml fullscreen окно

Qml fullscreen окно

Необходимо отрисовать главное окно в фулскринеПодскажите как это сделать! Нагугли что можно выводить так :

198
Java не видит классы

Java не видит классы

Решил потренироваться на сборке LineageСам сервер поднимается нормально, но не грузиться ни один квест

167
Как заполнить datePicker Java Selenium/Selenide

Как заполнить datePicker Java Selenium/Selenide

Подскажите пожалуйстаКак заполнить дату в datePicker?

319