C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

How to over load operator << for all sequential std containe

 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated)
View previous topic :: View next topic  
Author Message
H. Jiang
Guest





PostPosted: Sun Aug 06, 2006 11:44 pm    Post subject: How to over load operator << for all sequential std containe Reply with quote



I'm trying to overload operator << for sequential std containers, so
that I can print a vector or list v using something like

cout << v << endl;

Right now my solution is to hide the overloaded operator in a
namespace:

namespace very_private_ns {
template<typename C>
ostream & operator<<(ostream &os, C v)
{
std::operator<<(os, "[\t");
copy(v.begin(), v.end(),
ostream_iterator<typename C::value_type>(os, "\t"));
std::operator<<(os, "]");
return os;
}
}

and then add definitions for each container type:

template<typename T>
ostream & operator<<(ostream &os, vector<T> v)
{
return very_private_ns::operator<<(os, v);
}

template<typename T>
ostream & operator<<(ostream &os, list<T> v)
{
return very_private_ns::operator<<(os, v);
}

Does anyone have a more elegant solution?
Thanks.


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Ulrich Eckhardt
Guest





PostPosted: Mon Aug 07, 2006 9:10 am    Post subject: Re: How to over load operator << for all sequential std cont Reply with quote



H. Jiang wrote:
Quote:
I'm trying to overload operator << for sequential std containers, so
that I can print a vector or list v using something like

cout << v << endl;

Picking up on the 'something like', I'd use a proxy instead:

cout << print_seq(v) << std::endl;

implemented like this (roughly, untested):

// proxy to hold relevant data
template<typename ContainerT>
struct sequence_print_proxy
{
typename ContainerT::const_iterator beg;
typename ContainerT::const_iterator end;
char const* sep;
char const* sot;
char const* eot;
};
// operator << for proxy
// TODO: enhance with parameters
// - typename CharT
// - typename TraitsT=char_traits<CharT>
template<typename ContainerT>
ostream&
operator<<( ostream&, sequence_print_proxy const&) {..}

// factory-function
// Reason: you can't invoke a ctor of above proxy without fully
// qualifying its type, whereas the function can deduce the types,
// i.e. less typing.
template<typename ContainerT>
sequence_print_proxy<ContainerT>
print_seq( ContainerT const& c,
char const* sep = "\t",
char const* sot="[",
char const* eot="]")
{
sequence_print_proxy<ContainerT> res =
{ c.begin(), c.end(), sep, sot, eot };
return res;
}



Quote:
template<typename C
ostream & operator<<(ostream &os, C v)
[...]
template<typename T
ostream & operator<<(ostream &os, vector<T> v)
{
return very_private_ns::operator<<(os, v);
}

template<typename T
ostream & operator<<(ostream &os, list<T> v)
{
return very_private_ns::operator<<(os, v);
}

You are aware that you are passing by value here, right? Why?

Uli


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Hrayr BABAJANYAN
Guest





PostPosted: Mon Aug 07, 2006 9:10 am    Post subject: Re: How to over load operator << for all sequential std cont Reply with quote



Hi!
H. Jiang wrote:
Quote:
I'm trying to overload operator << for sequential std containers, so
that I can print a vector or list v using something like

cout << v << endl;

Right now my solution is to hide the overloaded operator in a
namespace:

namespace very_private_ns {
template<typename C
ostream & operator<<(ostream &os, C v)
{
std::operator<<(os, "[\t");
copy(v.begin(), v.end(),
ostream_iterator<typename C::value_type>(os, "\t"));
std::operator<<(os, "]");
return os;
}
}

and then add definitions for each container type:

template<typename T
ostream & operator<<(ostream &os, vector<T> v)
{
return very_private_ns::operator<<(os, v);
}

template<typename T
ostream & operator<<(ostream &os, list<T> v)
{
return very_private_ns::operator<<(os, v);
}

Does anyone have a more elegant solution?
Thanks.



Try this one:

template<typename T, template<typename U> class C>
std::ostream& operator<<(std::ostream& os, const C<T>& c)
{
// some generic code to print the content of the container
// for example:
os << "(";
for (typename C<T>::const_iterator i = c.begin(); i != c.end(); ++i)
os << *i << ", ";
os << ")";

return (os);
}

Cheers!
--
Hrayr


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Arne
Guest





PostPosted: Mon Aug 07, 2006 9:10 am    Post subject: Re: How to over load operator << for all sequential std cont Reply with quote

H. Jiang schrieb:

Quote:
I'm trying to overload operator << for sequential std containers, so
that I can print a vector or list v using something like

cout << v << endl;

....

Does anyone have a more elegant solution?
Thanks.
Hi,

you could use template template parameters like so:
template<class ValueType, class Allocator, template<class, class> class
StdSequenceContainer>
std::ostream& operator<<(std::ostream& os,
StdSequenceContainer<ValueType, Allocator>const& v)
{
return very_private_ns::operator<<(os, v);
}

Regards,
Arne


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Earl Purple
Guest





PostPosted: Mon Aug 07, 2006 8:52 pm    Post subject: Re: How to over load operator << for all sequential std cont Reply with quote

Ulrich Eckhardt wrote:

Quote:
// proxy to hold relevant data
template<typename ContainerT
struct sequence_print_proxy
{
typename ContainerT::const_iterator beg;
typename ContainerT::const_iterator end;
char const* sep;
char const* sot;
char const* eot;
};
// operator << for proxy
// TODO: enhance with parameters
// - typename CharT
// - typename TraitsT=char_traits<CharT
template<typename ContainerT
ostream&
operator<<( ostream&, sequence_print_proxy const&) {..}

// factory-function
etc.


This works well for vector and list but for map you run into the
problem that the value-type is std::pair and you need a custom way to
output that too.

For that you can write a specialist class and it's easy enough.

It is far more difficult to write the one reading in the other way. At
least if you want custom delimiters and then you can't use
istream_iterator, but instead you use getline a number of times with
different endings - first of all with your eos (end of sequence). That
assumes of course that your eos and delimiters never appear in any of
the tokens.


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
H. Jiang
Guest





PostPosted: Mon Aug 07, 2006 8:53 pm    Post subject: Re: How to over load operator << for all sequential std cont Reply with quote

Quote:
template<typename T
ostream & operator<<(ostream &os, vector<T> v)
{
return very_private_ns::operator<<(os, v);
}

template<typename T
ostream & operator<<(ostream &os, list<T> v)
{
return very_private_ns::operator<<(os, v);
}

You are aware that you are passing by value here, right? Why?

Thanks. You are right. It should have been const reference.


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated) All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.