By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
448,677 Members | 1,236 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 448,677 IT Pros & Developers. It's quick & easy.

std::list wrapper (+templates)

P: n/a
template <class T>
class List {
public:
List();
List(const List&);
List(int, const T&);

void push_back(const T &);
void push_front(const T &);
void pop_back();
void pop_front();
void remove(const T &);
int size();

friend std::ostream &operator<<(std::ostream &out, const List<T&);
private:
std::list<T*lst;
};

template <class T>
List<T>::List() { lst = new std::list<T>(); }

template <class T>
List<T>::List(const List &rhs) { lst = new std::list<T>(rhs.lst); }

template <class T>
List<T>::List(int n, const T& value) { lst = new std::list<T>(n,
value); }

template <class T>
void List<T>::push_back(const T& value) { lst->push_back(value); }

template <class T>
void List<T>::push_front(const T& value) { lst->push_front(value); }

template <class T>
void List<T>::pop_back() { lst->pop_back; }

template <class T>
void List<T>::pop_front() { lst->pop_front; }

template <class T>
void List<T>::remove(const T& value) { lst->remove(value); }

template <class T>
int List<T>::size() { return (int)lst->size; }

template <class T>
std::ostream &operator<<(std::ostream &out, const List<T&L)
{
for (std::list<T>::iterator it = L.lst->begin(); it != L.lst->end(); +
+it)
out << " " << *it;

out << std::endl;
return out;
}

int main()
{
List<intil;

for (int i = 0; i < 10; ++i)
il.push_back(i);

std::cout << il;

return 0;
}

There's a crazy problem with operator>MSVS6 says that 'lst' is
undeclared... I'm astounded... GNU G++ says that 'it' (the iterator in
operator>>) is not declared in this scope..
Jun 27 '08 #1
Share this Question
Share on Google+
12 Replies


P: n/a
is********@gmail.com wrote:
template <class T>
class List {
public:
List();
List(const List&);
List(int, const T&);

void push_back(const T &);
void push_front(const T &);
void pop_back();
void pop_front();
void remove(const T &);
int size();

friend std::ostream &operator<<(std::ostream &out, const List<T&);
I am not sure (friend declarations inside templates always confuse me)
but doesn't this declaration introduce a NON-template operator<<
function into the circulation?
private:
std::list<T*lst;
};

template <class T>
List<T>::List() { lst = new std::list<T>(); }

template <class T>
List<T>::List(const List &rhs) { lst = new std::list<T>(rhs.lst); }

template <class T>
List<T>::List(int n, const T& value) { lst = new std::list<T>(n,
value); }

template <class T>
void List<T>::push_back(const T& value) { lst->push_back(value); }

template <class T>
void List<T>::push_front(const T& value) { lst->push_front(value); }

template <class T>
void List<T>::pop_back() { lst->pop_back; }

template <class T>
void List<T>::pop_front() { lst->pop_front; }

template <class T>
void List<T>::remove(const T& value) { lst->remove(value); }

template <class T>
int List<T>::size() { return (int)lst->size; }

template <class T>
std::ostream &operator<<(std::ostream &out, const List<T&L)
{
for (std::list<T>::iterator it = L.lst->begin(); it != L.lst->end(); +
+it)
out << " " << *it;

out << std::endl;
return out;
}

int main()
{
List<intil;

for (int i = 0; i < 10; ++i)
il.push_back(i);

std::cout << il;

return 0;
}

There's a crazy problem with operator>MSVS6 says that 'lst' is
undeclared... I'm astounded... GNU G++ says that 'it' (the iterator in
operator>>) is not declared in this scope..
Well, MSVC6 is notoriously bad when it comes to templates. Download and
use their latest (2008) version, Express Edition. As for G++, it's
completely correct, 'std::list<T>::iterator' is not a type, you have to
tell the compiler that it's a type by means of 'typename' keyword:

for( typename std::list<T>::iterator it ...

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Jun 27 '08 #2

P: n/a
Thank you very much for 'for (typename ...)' . But there is still a
question about operator<<. You've said that this declaration introduce
a NON-template operator<< function into the circulation, but how to
use operator>with templates? Is it possible anyhow?
Jun 27 '08 #3

P: n/a
GNU G++ says: undefined reference to operator<<(std::ostream &,
List<intconst&);

One more question: why <int>?
Jun 27 '08 #4

P: n/a
is********@gmail.com wrote:
GNU G++ says: undefined reference to operator<<(std::ostream &,
List<intconst&);
That's right, I think you've stumbled upon the rule where if you declare
a straight-forward 'friend' in a class template, it declares a
non-template function as the friend, and now wants you to provide that
function (the declaration is there, but it cannot make the template the
definition for a non-template function declared in the 'friend'
declaration). Different compilers do different things in these
circumstances. And I am not sure how to straighten it out, sorry. Try
looking in the archives for 'template friend operator'...
One more question: why <int>?
Because your 'il' variable is of that type, isn't it?

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Jun 27 '08 #5

P: n/a
Hi!

Victor is right about the "declaration" problem: the friend declares a
non-template operator >>, but you only provide for a templated operator
>>. That's why the linker rejects the code.
is********@gmail.com schrieb:
friend std::ostream &operator<<(std::ostream &out, const List<T&);
In short: Don't use a friend at all.

There is no need to. Instead implement a member function "void
printTo(std::ostream&) const" that does the job. Then define
"operator>>" to call "printTo". Look ma', no friends. :)
template <class T>
std::ostream &operator<<(std::ostream &out, const List<T&L)
{
L.printTo(out);
return out;

By the way, your class is missing an operator = which needs to copy your
pointer.

Regards,
Frank
Jun 27 '08 #6

P: n/a
Thanks, Frank, 'printTo' works OK. But I solved the problem of friend
operator:

template <class Tclass List;

template <class Ustd::ostream& operator<< (std::ostream &, const
List<U&);

template <class T>
class List {
public:
// ...
template <class U>
friend std::ostream &operator<<(std::ostream &, const List<U&);
private:
std::list<T*lst;
};

// ...
template <class U>
std::ostream &operator<<(std::ostream &out, const List<U&L)
{
for (typename std::list<U>::iterator it = L.lst->begin(); it !=
L.lst->end(); ++it)
out << " " << *it;

out << std::endl;
return out;
}

int main()
{
List<intil;

for (int i = 0; i < 10; ++i)
il.push_back(i);

std::cout << il;

return 0;
}
Jun 27 '08 #7

P: n/a
Thanks, Frank, 'printTo' works OK. But I solved the problem of friend
operator:

template <class Tclass List;

template <class Ustd::ostream& operator<< (std::ostream &, const
List<U&);

template <class T>
class List {
public:
// ...
template <class U>
friend std::ostream &operator<<(std::ostream &, const List<U&);
private:
std::list<T*lst;
};

// ...
template <class U>
std::ostream &operator<<(std::ostream &out, const List<U&L)
{
for (typename std::list<U>::iterator it = L.lst->begin(); it !=
L.lst->end(); ++it)
out << " " << *it;

out << std::endl;
return out;
}

int main()
{
List<intil;

for (int i = 0; i < 10; ++i)
il.push_back(i);

std::cout << il;

return 0;
}
Jun 27 '08 #8

P: n/a
Hey, gentlemen, it's interesting, but there's one more equivalent form
of doing this:
using namespace std;

template <class Tclass List;
template <class Uostream& operator<< (ostream &, const List<U&);

template <class Tclass List {
public: //...
friend ostream &operator<< <T(ostream &, const List<T>
&); //!!!
private:
std::list<T*lst;
};
//...
template <class Tostream& operator<<(ostream &out, const List<T&L)
{
for (typename list<T>::iterator it = L.lst->begin(); it != L.lst-
>end(); ++it)
out << " " << *it;

out << std::endl;
return out;
}
//...
Jun 27 '08 #9

P: n/a
Hi!

is********@gmail.com schrieb:
Hey, gentlemen, it's interesting, but there's one more equivalent form
of doing this:
[snip]
friend ostream &operator<< <T(ostream &, const List<T>
&); //!!!
Yes. That is the declaration of a templated method. And yes, you need to
first declare the whole function (the "template<typename Tostream&
operator << (ostream&, const List<T>&);" line).

And this friend declaration is just the minimal friend declaration you
need. Your previous post made all instances of the template method a friend.

Regards, Frank
Jun 27 '08 #10

P: n/a

<is********@gmail.comwrote in message
news:31**********************************@e39g2000 hsf.googlegroups.com...
template <class T>
class List {
public:
List();
List(const List&);
List(int, const T&);

void push_back(const T &);
void push_front(const T &);
void pop_back();
void pop_front();
void remove(const T &);
int size();

friend std::ostream &operator<<(std::ostream &out, const List<T&);
private:
std::list<T*lst;
};

template <class T>
List<T>::List() { lst = new std::list<T>(); }

template <class T>
List<T>::List(const List &rhs) { lst = new std::list<T>(rhs.lst); }
[...]

Where are you deleting the above allocation? I see no dtor in List<T>...

Jun 27 '08 #11

P: n/a
On 21 Mai, 21:45, "isligue...@gmail.com" <isligue...@gmail.comwrote:
[snip]
List<T>::List() { lst = new std::list<T>(); }
It's a good idea to use an initializer list for this:
List<T>::List() : lst(new std::list<T>) {}
template <class T>
List<T>::List(const List &rhs) { lst = new std::list<T>(rhs.lst); }
This copy ctor is ill-formed (as you will quickly notice if you try to
use it). Also, prefer to use an initializer list here too.
template <class T>
int List<T>::size() { return (int)lst->size; }
It may be a good idea to use an unsigned type here (size_t comes to
mind), since all the standard containers use this (Just a suggestion).

DP
CAPTCHA: inact
Jun 27 '08 #12

P: n/a
On 2008-05-23 02:03:23 -0400, Triple-DES <De**********@gmail.comsaid:
On 21 Mai, 21:45, "isligue...@gmail.com" <isligue...@gmail.comwrote:
[snip]
>List<T>::List() { lst = new std::list<T>(); }

It's a good idea to use an initializer list for this:
List<T>::List() : lst(new std::list<T>) {}
>template <class T>
List<T>::List(const List &rhs) { lst = new std::list<T>(rhs.lst); }

This copy ctor is ill-formed (as you will quickly notice if you try to
use it). Also, prefer to use an initializer list here too.
>template <class T>
int List<T>::size() { return (int)lst->size; }

It may be a good idea to use an unsigned type here (size_t comes to
mind), since all the standard containers use this (Just a suggestion).
Even better would be std::list<T>::size_type.

--
Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com) Author of "The
Standard C++ Library Extensions: a Tutorial and Reference
(www.petebecker.com/tr1book)

Jun 27 '08 #13

This discussion thread is closed

Replies have been disabled for this discussion.