пишу бинарное дерево и наткнулся на очень непонятную мне ошибку, вот пример:
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
.
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Перевод документов на английский язык: Важность и ключевые аспекты
Необходимо отрисовать главное окно в фулскринеПодскажите как это сделать! Нагугли что можно выводить так :
Решил потренироваться на сборке LineageСам сервер поднимается нормально, но не грузиться ни один квест
Подскажите пожалуйстаКак заполнить дату в datePicker?