0

I can't figure out the correct syntax for templated friend overloaded operators. Using the code (I'm only showing the relevant stuff) from the class header (please don't tell me to change anything from this section):

#include <iostream>
using namespace std;

template <typename T>
class List;
template <typename T>
class Queue;
template <typename T>
class Stack;

template <typename T>
class Node{
   private:
      friend class List<T>;
      friend class Stack<T>;
      friend class Queue<T>;
      friend ostream& operator<< <>(const ostream&, const List<T>&);
      friend ostream& operator<< <>(const ostream&, const Stack<T>&);
      friend ostream& operator<< <>(const ostream&, const Queue<T>&);
};

template <typename T>
class List{
   public:
      friend ostream& operator<< <>(const ostream&, const List<T>&);
};

template <typename T>
class Stack{
   public:
      friend ostream& operator<< <>(const ostream&, const Stack<T>&);
};

template <typename T>
class Queue{
   public:
      friend ostream& operator<< <>(const ostream&, const Queue<T>&);
};

This is where the implementation comes into play, and I can't figure out the syntax.

template <typename T>
ostream& operator<<(const ostream& cout, const List<T>& toPrint){ <-- what do I change here?
   // irrelevant body
   }

template <typename T>
ostream& operator<<(const ostream& cout, const Stack<T>& toPrint){ <-- what do I change here?
   // irrelevant body
   }

template <typename T>
ostream& operator<<(const ostream& cout, const Queue<T>& toPrint){ <-- what do I change here?
   // irrelevant body
   }

What do I need to change in each of those three lines to make this work?

I keep getting compiler errors:

error: template-id ‘operator<< <>’ for ‘std::ostream& operator<<(const ostream&, const Queue<Card>&)’ does not match any template declaration
Bobazonski
  • 1,515
  • 5
  • 26
  • 43

2 Answers2

1

I guess it might be those:

  friend ostream& operator<< <>(const ostream&, const List<T>&);
  friend ostream& operator<< <>(const ostream&, const Stack<T>&);
  friend ostream& operator<< <>(const ostream&, const Queue<T>&);

lines. You didn't specify the type of a template:

  friend ostream& operator<< <T>(ostream&, const List<T>&);
  friend ostream& operator<< <T>(ostream&, const Stack<T>&);
  friend ostream& operator<< <T>(ostream&, const Queue<T>&);

so compiler couldn't match declarations with definitions.

So declarations:

friend ostream& operator<< <T>(const ostream&, const List<T>&);

and definitions:

template <typename T>
ostream& operator<<(ostream& cout, const List<T>& toPrint) {
    // irrelevant body
}

Also to prevent compiler from complaining about not declared templates add declarations before class definition.

Final results:

#include <iostream>
using namespace std;


// Class delcarations - we need them to declare functions

template <typename T>
class List;
template <typename T>
class Stack;
template <typename T>
class Queue;


// operator<< function declaration informs compiler that there is function that can be befriended

template <typename T>
ostream& operator<<(ostream&, const List<T>&);
template <typename T>
ostream& operator<<(ostream&, const Stack<T>&);
template <typename T>
ostream& operator<<(ostream&, const Queue<T>&);


// Class definitions

template <typename T>
class Node{
    private:
        friend class List<T>;
        friend class Stack<T>;
        friend class Queue<T>;
};

template <typename T>
class List{
    public:
        friend ostream& operator<< <T>(ostream&, const List<T>&);
};

template <typename T>
class Stack{
    public:
        friend ostream& operator<< <T>(ostream&, const Stack<T>&);
};

template <typename T>
class Queue{
    public:
        friend ostream& operator<< <T>(ostream&, const Queue<T>&);
};


// Actual implemetations

template <typename T>
ostream& operator<<(ostream& out, const List<T>& toPrint) {
    out << "List";
    return cout;
}

template <typename T>
ostream& operator<<(ostream& out, const Stack<T>& toPrint) {
    out << "Stack";
    return out;
}

template <typename T>
ostream& operator<<(ostream& out, const Queue<T>& toPrint) {
    out << "Queue";
    return out;
}

// Template instantations test

int main() {
    List<int>  list;
    Stack<int> stack;
    Queue<int> queue;

    cout << list  << endl
         << stack << endl
         << queue << endl;

    return 0;
}

for me it printed:

List
Stack
Queue

Here and here you have some nice examples.

EDIT: You were right, I made some mistakes. Corrected the answer to the working one.

Mateusz Kubuszok
  • 24,995
  • 4
  • 42
  • 64
  • Your solution did not work. I get this compiler message: `error: function template partial specialization ‘operator<< ’ is not allowed` when replacing each `<>` with `` and adding `` following each `<<` in the definitions. – Bobazonski Dec 03 '13 at 21:16
0

there are some weird things here.

firstly the error message renders ostream differently, the fact that it qualifies the return value as std::ostream& and not the parameter parsed in seems a bit fishy - but it could be a red herring.

it is always a shame to see "using namespace std;". i consider the using keyword to be absolutely forbidden - so i have no idea what problems or changes this might cause. i simply suspect it is related.

now - to debug this properly i'd suggest replacing the operator and friend with regular function templates and breaking the access levels to allow that test (i.e. remove private etc.), then introduce each element one at a time until you find which part is actually causing the problem.

jheriko
  • 3,043
  • 1
  • 21
  • 28