пишу бинарное дерево и наткнулся на очень непонятную мне ошибку, вот пример:
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?)
При использовании квалифицированного имени вложенного типа (т.е. имени вида 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.
Апостиль в Лос-Анджелесе без лишних нервов и бумажной волокиты
Основные этапы разработки сайта для стоматологической клиники
Продвижение своими сайтами как стратегия роста и независимости