Re: does not compile with "using namespace std"

From: Denis Remezov (firstname_surname_at_yahoo.removethis.ca)
Date: 07/20/04


Date: Tue, 20 Jul 2004 02:59:46 +0000

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



Relevant Pages

  • Re: Class templates and friend function templates
    ... friend void process; ... each specialization of the `task' class template has all specializations of the function template `func' as friends. ... It only has one parameter that is distinct, thus implying a kind of partial specialisation of the friend declaration once C is instantiated for a particular type. ...
    (microsoft.public.vc.language)
  • Re: Class templates and friend function templates
    ... >> Function template doesn't support partial specialization. ... > issue is the specialisation of the *friend declaration*, ... > appearance of allowing a partial specialisation of the ...
    (microsoft.public.vc.language)
  • Re: Circular Class Template Friendship
    ... > My issue is the syntax of declaring a friend class within ... > which the string is a fixed width that is specialized. ... it is still possible to have Name_Id_Table template ... the friend class declaration. ...
    (comp.lang.cpp)
  • Re: Class templates and friend function templates
    ... > It never occurred to me that the friend declaration could be an overload. ... > template ... I suspect the online version uses an EDG option to "instantiate ...
    (microsoft.public.vc.language)
  • Re: Template friendship to nested template class
    ... friend struct INNER; ... Probably you are missing an EXTRA template to declare ... I think it's because the name referred to in a 'friend' declaration is looked up to exist at the namespace scope. ...
    (microsoft.public.vc.language)