Douglas wrote:
**** Post for FREE via your newsreader at post.usenet.com ****
Hello,
The following code does not compile if line 3 is uncommented "using
namespace std".
I do not understand it. Could somebody explain it to me? I am using MSVC
6.0.
Thanks a lot,
Douglas
While I cannot give you any insight on the way MSVC 6.0 works, your
code does have a problem that needs fixing, one way or the other,
or else it will not work on more conforming compilers.
See comments below (only on that specific problem, ignoring other
issues).
Error message is:
C:\test\stacktest.cpp(36) : error C2248: 'sp' : cannot access private member
declared in class 'Stack<char>'
// --------------- CODE STARTS HERE --------------------------
#include <iostream>
#define STACK_SIZE 10
// using namespace std; // It does not compile unless this line is
commented.
using std::ostream;
using std::cin;
using std::cout;
template<class T> class Stack {
public:
Stack() {items = new T[STACK_SIZE]; sp = -1;}
~Stack() {delete [ ] items;}
T top() const { return items[sp];}
T pop() {return items[sp--];}
void push(T i) {items[++sp] = i;}
friend ostream& operator<< (ostream &, Stack<T>&); // return type was
ostream&
The above is a declaration of a normal function, not a function
template. That means that a specialisation of class Stack for some
template parameter T will have the following function
ostream& operator <<(ostream&, Stack<T>&);
as a friend. Again, the above is a normal function, not a
specialisation of a function template.
private:
T* items;
int sp;
st
^^
Just a typo, I guess.
};
template<class T>
ostream& operator<<(ostream & output, Stack<T> &a) //output type was
ostream&
{
cout << "\n\nElements in stack are: ";
for (int i=0; i< STACK_SIZE; i++)
output << a.pop();
output << a.sp;
return output;
}
Now this is a function template, which is unrelated to the declaration
friend ostream& operator <<(ostream&, Stack<T>&);
above.
Your code should compile with the right compiler, but it won't link
because you haven't provided a definition for the friend operator <<.
There are several ways you can implement what you want, but I'm not
sure which one of them (if any) VC 6.0 will accept (I'm not bashing
MSVC, I just cannot take it for a test run).
0. Define what you have declared, a properly typed operator << for
your Stack specialisation:
ostream& operator <<(ostream& output, Stack<char>& a) {...}
It's a kludge. I would avoid using it if at all possible.
1. Declare your friend as
friend ostream& operator<< <>(ostream &, Stack<T>&);
in which case you will also need a couple of forward declarations
just before the line "template<class T> class Stack {":
template<class T> class Stack;
template<class T>
ostream& operator <<(ostream& output, Stack<T>& a);
The effect is that a specialisation of Stack will have a
corresponding specialisation of the /function template/ operator <<
as a friend. Leave the definition of operator << as it is.
2. You can let the Stack declare a friend template:
template <class T1>
friend ostream& operator <<(ostream &, Stack<T1>&);
Now all specialisations of this operator << will be friends of
any specialisation of Stack. Though this probably won't be a
big problem, it is likely not what you really want either.
#1 should be the default choice to consider.
All of the above should work. If everything fails, you can at least
use a work-around: define a public member function for the Stack class
template:
ostream& print(ostream& s) {...}
that does all of the job the operator << is supposed to do. Then
make operator << template call this function.
(I think all of the above has been discussed here before, I've
just restored it by memory).
Denis