По объявляющему друга оператора, компилятору искать функцию
ostream& operator<<(ostream &,T);
где T
точно такой же тип шаблон класса ВТКЕЕ инстанцируется. (Например, для btree<Node>
, фактическая подпись будет ostream& operator<<(ostream &, Node);
- если вы зайца членов i
и n
типа Node
)
Эта функция будет иметь доступ к частным и защищенным членам (переменные и функции) класса btree<T>
для всех случаев от T
, но на самом деле он не является членом класса (как и без ключевого слова friend
).
Оператор определение вы предоставляете для оператора, который является членом класса шаблона BTree, как если у вас есть объявили
template<class T>
class btree
{
public:
ostream& operator<<(ostream &,T);
};
Это связано с btree<T>::
префиксом включен (т.е. определяет класс, к которому принадлежит функция/operator).
Поскольку в этом классе нет соответствующего оператора декларации (см. Вышеприведенное описание объявления друга), компилятор жалуется.
Чтобы исправить это, вы либо
- держать друг декларацию, удалите
btree<T>::
префикс и template<class T>
от оператора Defintion и изменить второй тип параметра в btree<Type>&
, где Type
является одним из типы, которые вы ожидаете создать экземпляр btree-шаблона (например, Node
), - тогда поставьте аналогичные дефекты для других подобных типов.
- или удалить
friend
ключевое слово из декларации в классе и удалить параметр T
как из декларации и определения как теперь оператор должен работать на всем BTree (который неявно поставляются через *this
).
- В качестве альтернативы, вы можете поэкспериментировать с объявляя друг оператор в качестве шаблона, но это требует еще несколько модификаций: (подробнее о forward declaration)
template<class T> btree; // forward declaration of class btree
// forward declare operator (or move definition here)
template<class T>
ostream& operator<<(ostream &o, btree<T>& s);
// declare operator as template friend
template<class T>
class btree
{
public:
friend ostream& operator<< <> (ostream &, bree<T>&);
// note <> after operator name to denote template with no new template parameters
};
Обратите внимание, что выше я предположил, что вы хотите вывести все дерево (то есть вызывать operator<<
на объект btree). Из кода, который у вас есть, неясно, является ли это вашим намерением (класс btree не имеет членов i
и n
). Если нет и тип, который вы хотите вызвать оператора <<
, то это фактический параметр шаблона btree, тогда вам не нужно менять второй параметр шаблонизированного оператора с T
, но также нет необходимости объявлять это как friend
класса btree, так как оператор не зависит от btree. Вам необходимо объявить его как друга класса, чьи члены i
и n
у вас есть доступ к определенному оператору определенному (например, Узел выше), если i
и/или n
являются частными в этом классе. Понятие о потере btree<T>::
(или Node::
) по-прежнему применяется, поскольку оператор не принадлежит ни одному классу.
Пара больше вещей, если вы идете с другом объявлении:
- Тип второго параметра оператора должен быть
btree<T>&
(акцент на &
), поскольку это является более эффективным, чтобы передать reference к btree, чем для копирования всего btree (или мелкой копии, если вы используете указатели и переходите по умолчанию copy-contructor)
- второй параметр также должен быть помечен как
const
, так как (предположительно) вы не хотите изменять объект btree во время вывод. Имейте в виду, что в этом случае вам нужно будет отметить некоторые не меняющиеся методы в btree<T>
как const
, а также разрешить его компиляцию. (См справку по const correctness)
EDIT'd несколько раз, чтобы понять и обеспечить корректность
http://sscce.org/ (особенно ** простой **). – Griwes
Код выглядит длинным, но проблема в классе btree и перегруженной << операторной функции, которая сразу же следует за классом. – user1232138
@OP, каждый раз, когда я вижу такую высокую полосу прокрутки, это указывает на неправильную тестовую запись. Удалите все, что необходимо, и тогда это будет «Простой, самосохраненный правильный пример». – Griwes