 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
H. Jiang Guest
|
Posted: Sun Aug 06, 2006 11:44 pm Post subject: How to over load operator << for all sequential std containe |
|
|
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
|
Posted: Mon Aug 07, 2006 9:10 am Post subject: Re: How to over load operator << for all sequential std cont |
|
|
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
|
Posted: Mon Aug 07, 2006 9:10 am Post subject: Re: How to over load operator << for all sequential std cont |
|
|
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
|
Posted: Mon Aug 07, 2006 9:10 am Post subject: Re: How to over load operator << for all sequential std cont |
|
|
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
|
Posted: Mon Aug 07, 2006 8:52 pm Post subject: Re: How to over load operator << for all sequential std cont |
|
|
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
|
Posted: Mon Aug 07, 2006 8:53 pm Post subject: Re: How to over load operator << for all sequential std cont |
|
|
| 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 |
|
 |
|
|
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
|
|