473,379 Members | 1,530 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,379 software developers and data experts.

Friend functions and template classes

Hello, all I'm having a problem with friend functions in a templatized Queue
class I'm writing using linked lists. The problem is that I can't get the
friend function to be able to access private data from the class. Here's
the gist of the code:

template <class T>
struct NodeType
{
T data;
NodeType<T> * link;
};

template <class T>
class Queue1
{
friend ostream & operator<< (ostream & lhs, const Queue1 <T> & rhs);
// some public methods & stuff here
private:
NodeType <T> * head;
NodeType <T> * tail;
};

template <class T>
ostream & operator<< (ostream & lhs, const Queue1 <T> & rhs)
{
NodeType <T> * pIterator = rhs.tail;
return &lhs;
}

The problem I get is that in the operator<< function my compiler (Visual C++
6) is reporting:

'tail' : cannot access private member declared in class 'Queue1<char>'

(this is of course using a driver program that declares a Queue1<char>
object).

Any suggestions would be appreciated.

Adam

Jul 22 '05 #1
6 2315
"Adam Parkin" <sk****@dfaslk.com> wrote...
Hello, all I'm having a problem with friend functions in a templatized Queue class I'm writing using linked lists. The problem is that I can't get the
friend function to be able to access private data from the class. Here's
the gist of the code:

template <class T>
struct NodeType
{
T data;
NodeType<T> * link;
};
I think you need to do a bit of a declaration dance. Put here:

template<class T> class Queue1;
template<class T> ostream& operator <<(ostream&, const Queue1<T>&);
template <class T>
class Queue1
{
friend ostream & operator<< (ostream & lhs, const Queue1 <T> & rhs);
Change this to

friend ostream& operator<< <T>(ostream&, const Queue1&);
// some public methods & stuff here
private:
NodeType <T> * head;
NodeType <T> * tail;
};

template <class T>
ostream & operator<< (ostream & lhs, const Queue1 <T> & rhs)
{
NodeType <T> * pIterator = rhs.tail;
return &lhs;
You probably meant

return lhs;

here. BTW, avoid typing your program directly into a posting.
}

The problem I get is that in the operator<< function my compiler (Visual C++ 6) is reporting:

'tail' : cannot access private member declared in class 'Queue1<char>'

(this is of course using a driver program that declares a Queue1<char>
object).


---------------------------------------------- This code
#include <iostream>
using namespace std;

template <class T>
struct NodeType
{
T data;
NodeType<T> * link;
};

template<class T> class Queue1;
template<class T> ostream& operator <<(ostream&, const Queue1<T>&);

template <class T>
class Queue1
{
friend ostream & operator<< <T>(ostream &, const Queue1&);
// some public methods & stuff here
private:
NodeType <T> * head;
NodeType <T> * tail;
};

template <class T>
ostream & operator<< (ostream & lhs, const Queue1 <T> & rhs)
{
NodeType <T> * pIterator = rhs.tail;
return lhs;
}

int main()
{
Queue1<int> qi;
cout << qi;
return 0;
}

----------------------------------------------
compiles fine with Comeau and Intel. VC++ v6 refuses to compile it (due
to its very poor template handling abilities). A quick solution to this
would be a public member function

ostream& print(ostream& out) const
{
// do what you need
return out;
}

in the Queue1 template. The template output operator would call it:

template<class T> ostream& operator << (ostream& os, const Queue1<T>& t)
{
return t.print(os);
}
------------------------------- Full code that compiles with VC++
#include <iostream>
using namespace std;

template <class T>
struct NodeType
{
T data;
NodeType<T> * link;
};

template <class T>
class Queue1
{
public:
ostream & print(ostream & out) const
{
NodeType<T> *pIt = tail;
return out;
}
// some public methods & stuff here
private:
NodeType <T> * head;
NodeType <T> * tail;
};

template<class T>
ostream & operator<<(ostream & lhs, const Queue1<T> & rhs)
{
return rhs.print(lhs);
}

int main()
{
Queue1<int> qi;

cout << qi;

return 0;
}
------------------------------------------------------------
HTH

Victor
Jul 22 '05 #2
Adam Parkin wrote:
[snip]
template <class T>
class Queue1
{
friend ostream & operator<< (ostream & lhs, const Queue1 <T> & rhs);
// some public methods & stuff here
private:
NodeType <T> * head;
NodeType <T> * tail;
};

template <class T>
ostream & operator<< (ostream & lhs, const Queue1 <T> & rhs)
{
NodeType <T> * pIterator = rhs.tail;
return &lhs;
}
As Victor said, changing
friend ostream & operator<< (ostream & lhs, const Queue1 <T> & rhs);
to
friend ostream & operator<< <> (ostream & lhs, const Queue1 <T> & rhs);

(you can write <> instead of <T> here) would solve the problem with the
right compiler. Here is why: your definition of operator<< is a function
template; its friend declaration, if unqualified, must be a template-id
(just what you probably meant to do).

Any suggestions would be appreciated.


0. Get a better compiler.

There are a couple of alternatives that you could try as well.

1. Remember,
friend ostream & operator<< (ostream & lhs, const Queue1 <T> & rhs);

is a declaration of a function, not a function template, despite the <T>
in the argument list. That means that the compiler will need a corresponding
definition. Replace your definition of operator<< with the following
(but keep your original friend declaration):

ostream & operator<< (ostream & lhs, const Queue1 <char> & rhs)
{
NodeType <char> * pIterator = rhs.tail;
return lhs;
}

Note that this is not a template specialisation. I wouldn't like doing it
this way, but it is still standard, and maybe VC++6 will accept it.
2. Finally, you may try the following: qualify the declaration of the friend
operator<< with :: and predeclare it (rules are different for qualified names
in this case):

template <class T>
class Queue1;

template <class T>
ostream & operator<< (ostream & lhs, const Queue1 <T> & rhs);

template <class T>
class Queue1
{
friend ostream & ::operator<< <> (ostream & lhs, const Queue1 <T> & rhs);
// some public methods & stuff here
private:
NodeType <T> * head;
NodeType <T> * tail;
};
Denis
Jul 22 '05 #3
"Denis Remezov" <RE*********************@yahoo.removethis.ca> wrote...
Adam Parkin wrote:
[snip]

template <class T>
class Queue1
{
friend ostream & operator<< (ostream & lhs, const Queue1 <T> & rhs);
// some public methods & stuff here
private:
NodeType <T> * head;
NodeType <T> * tail;
};

template <class T>
ostream & operator<< (ostream & lhs, const Queue1 <T> & rhs)
{
NodeType <T> * pIterator = rhs.tail;
return &lhs;
}


As Victor said, changing
friend ostream & operator<< (ostream & lhs, const Queue1 <T> & rhs);
to
friend ostream & operator<< <> (ostream & lhs, const Queue1 <T> & rhs);

(you can write <> instead of <T> here) would solve the problem with the
right compiler. Here is why: your definition of operator<< is a function
template; its friend declaration, if unqualified, must be a template-id
(just what you probably meant to do).

Any suggestions would be appreciated.


0. Get a better compiler.

There are a couple of alternatives that you could try as well.

1. Remember,
friend ostream & operator<< (ostream & lhs, const Queue1 <T> & rhs);

is a declaration of a function, not a function template, despite the <T>
in the argument list. That means that the compiler will need a

corresponding definition. Replace your definition of operator<< with the following
(but keep your original friend declaration):

ostream & operator<< (ostream & lhs, const Queue1 <char> & rhs)
{
NodeType <char> * pIterator = rhs.tail;
return lhs;
}

Note that this is not a template specialisation. I wouldn't like doing it
this way, but it is still standard, and maybe VC++6 will accept it.
2. Finally, you may try the following: qualify the declaration of the friend operator<< with :: and predeclare it (rules are different for qualified names in this case):

template <class T>
class Queue1;

template <class T>
ostream & operator<< (ostream & lhs, const Queue1 <T> & rhs);

template <class T>
class Queue1
{
friend ostream & ::operator<< <> (ostream & lhs, const Queue1 <T> & rhs);
VC++ chokes on this. I gave a solution, and of course, your option 0
is just fine too.

Victor
// some public methods & stuff here
private:
NodeType <T> * head;
NodeType <T> * tail;
};
Denis

Jul 22 '05 #4
"Denis Remezov" <RE*********************@yahoo.removethis.ca> wrote in
message news:40***************@yahoo.removethis.ca...
As Victor said, changing
friend ostream & operator<< (ostream & lhs, const Queue1 <T> & rhs);
to
friend ostream & operator<< <> (ostream & lhs, const Queue1 <T> & rhs);

(you can write <> instead of <T> here) would solve the problem with the
right compiler.
And of course VC6 is not the right compiler, as this doesn't work.
Any suggestions would be appreciated.


0. Get a better compiler.


LOL, thanks. :-p
is a declaration of a function, not a function template, despite the <T>
in the argument list. That means that the compiler will need a corresponding definition. Replace your definition of operator<< with the following
(but keep your original friend declaration):

ostream & operator<< (ostream & lhs, const Queue1 <char> & rhs)
{
Hehe, funny enough, VC6 reports this as "binary '<<' : no operator defined
which takes a right-hand operand of type 'class Queue1<char>' (or there is
no acceptable conversion)", even though I've explicitly included the <char>
in my function definition.

2. Finally, you may try the following: qualify the declaration of the friend operator<< with :: and predeclare it (rules are different for qualified names in this case):

template <class T>
class Queue1;

template <class T>
ostream & operator<< (ostream & lhs, const Queue1 <T> & rhs);


Yeah, I actually found this code on a few websites, but no, it doesn't work
under VC6 (or at least didn't for me). Thanks for the help.

Adam
Jul 22 '05 #5
"Victor Bazarov" <v.********@comAcast.net> wrote in message
news:c4_hc.4892$0u6.1057800@attbi_s03...
"Adam Parkin" <sk****@dfaslk.com> wrote...
Hello, all I'm having a problem with friend functions in a templatized

Queue
class I'm writing using linked lists. The problem is that I can't get the friend function to be able to access private data from the class. Here's the gist of the code:


Okay, figured out the problem, although I'm not entirely sure why it caused
a problem. My driver.cpp had:

#include "queue1.h"
#include <iostream>
using namespace std;

in it, and once I changed this to:

#include "queue1.h"
#include <iostream>
using std::cout;
using std::endl;

Everything worked fine, as the access of the private data member in
operator<< was now legal. Can somebody explain why changes in one module
(the Queue1.h file) were affected the way they were by the driver.cpp file?
Is it that there's something in the std namespace which conflicted with my
Queue1 module?

I suppose this is a lesson in don't be lazy, use scope resolution to be as
precise as possible.

Adam
Jul 22 '05 #6
"Adam Parkin" <sk****@dfaslk.com> wrote...
"Victor Bazarov" <v.********@comAcast.net> wrote in message
news:c4_hc.4892$0u6.1057800@attbi_s03...
"Adam Parkin" <sk****@dfaslk.com> wrote...
Hello, all I'm having a problem with friend functions in a templatized Queue
class I'm writing using linked lists. The problem is that I can't get the friend function to be able to access private data from the class. Here's the gist of the code:


Okay, figured out the problem, although I'm not entirely sure why it

caused a problem. My driver.cpp had:

#include "queue1.h"
#include <iostream>
using namespace std;

in it, and once I changed this to:

#include "queue1.h"
#include <iostream>
using std::cout;
using std::endl;

Everything worked fine, as the access of the private data member in
operator<< was now legal. Can somebody explain why changes in one module
(the Queue1.h file) were affected the way they were by the driver.cpp file? Is it that there's something in the std namespace which conflicted with my
Queue1 module?

I suppose this is a lesson in don't be lazy, use scope resolution to be as
precise as possible.


I don't have an answer to your question about the namespace and the
effect of it for the code, but I recommend asking the same question
in microsoft.public.vc.language. Of course, keep in mind that they
have been enjoying VC++ .NET probably longer on average than we here,
so they may be tempted to simply say, "it's fixed in v7.1, so get it
and the problem will go away"...

Victor
Jul 22 '05 #7

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

5
by: Ales DOLECEK | last post by:
Hello, I'm trying to created base class and template for "smart" pointer pointing to it. It should do simple reference counting and clean up when the reference count reaches zero. The header...
21
by: Sebastian Faust | last post by:
Hi, is a construction like the following possible: template<class view_model> class template_clase { protected: template_clase() {} virtual ~template_clase() {}
2
by: Christophe Barbe | last post by:
I posted a few days ago about the same problem but was not very clear. So here is my second take at it. Basically with GCC 3.3.2, I can't compile the example from the C++ FAQ Lite available...
5
by: Trevor Lango | last post by:
What is the appropriate syntax for placing a friend function that includes as one of it's parameters a pointer to the class object itself within the template class? I have the following: ...
5
by: Ruben Campos | last post by:
Some questions about this code: template <typename T> class MyTemplate; template <typename T> MyTemplate <T> operator- (const MyTemplate <T> & object); template <typename T> MyTemplate <T>...
15
by: Samee Zahur | last post by:
Question: How do friend functions and static member functions differ in terms of functionality? I mean, neither necessarily needs an object of the class to be created before they are called and...
3
by: Pierre Barbier de Reuille | last post by:
Hi, after reading the article " The Standard Librarian : Defining Iterators and Const Iterators" from Matt Austern:...
21
by: H9XLrv5oXVNvHiUI | last post by:
Hi, I have a question about injecting friend functions within template classes. My question is specific to gcc (version 3.4.5) used in combination with mingw because this code (or at least code...
3
by: mojmir | last post by:
hello, i have problem with following code (see below). compiler (vs2005sp1) complains that the call to fn is ambiguous: error C2668: 'BB::fn' : ambiguous call to overloaded function could be...
1
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...
0
by: ryjfgjl | last post by:
In our work, we often need to import Excel data into databases (such as MySQL, SQL Server, Oracle) for data analysis and processing. Usually, we use database tools like Navicat or the Excel import...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.