printing vectors


A

Andrea Crotti

I wanted something to display my vectors easily and in a nice way.
From the following site the "shortest" solution was this:

// from http://bytes.com/topic/c/answers/133231-print-elements-vector discussion
template <typename T>
void displayContainer(const T& v) {
copy(v.begin(), v.end(), ostream_iterator<typename T::value_type>(cout, ", "));
}

But I don't like it so much actually.

Also because if I want to add it to a class which uses a buffer, I would
like to do

ostream& operator<<(ostream& s, const MyClass& c)
{
s << c.vec;
return s;
}

which in this case is not possible but I have instead to call a
function.

I thought that something like this would be possible


template <typename T>
ostream& operator<<(ostream& s, const vector<T>& vec)
{
typename vector<T>::iterator iter;
for (iter=vec.begin(); iter!=vec.end(); ++iter) {
s << (*iter);
}
return s;
}

But actually I guess it's not, since then I don't know how to pass the
template parameter and I get this erro

try.cpp: In function ‘std::eek:stream& operator<<(std::eek:stream&, const std::vector<T, std::allocator<_CharT> >&) [with T = int]’:
try.cpp:21: instantiated from here
try.cpp:12: error: no match for ‘operator=’ in ‘iter = ((const
std::vector<int, std::allocator<int> >*)vec)->std::vector<_Tp,
_Alloc>::begin [with _Tp = int, _Alloc = std::allocator<int>]()’
 
Ad

Advertisements

L

Larry Evans

On 11/09/10 18:13, Andrea Crotti wrote:
[snip]
I thought that something like this would be possible


template <typename T>
ostream& operator<<(ostream& s, const vector<T>& vec)
{
typename vector<T>::iterator iter;
for (iter=vec.begin(); iter!=vec.end(); ++iter) {
s << (*iter);
}
return s;
}

But actually I guess it's not, since then I don't know how to pass the
template parameter and I get this erro

try.cpp: In function ‘std::eek:stream& operator<<(std::eek:stream&, const std::vector<T, std::allocator<_CharT> >&) [with T = int]’:
try.cpp:21: instantiated from here
try.cpp:12: error: no match for ‘operator=’ in ‘iter = ((const
std::vector<int, std::allocator<int> >*)vec)->std::vector<_Tp,
_Alloc>::begin [with _Tp = int, _Alloc = std::allocator<int>]()’

Have you tried:

typename vector<T>::const_iterator iter;

?
 
A

Andrea Crotti

Larry Evans said:
On 11/09/10 18:13, Andrea Crotti wrote:
[snip]
I thought that something like this would be possible


template <typename T>
ostream& operator<<(ostream& s, const vector<T>& vec)
{
typename vector<T>::iterator iter;
for (iter=vec.begin(); iter!=vec.end(); ++iter) {
s << (*iter);
}
return s;
}

But actually I guess it's not, since then I don't know how to pass the
template parameter and I get this erro

try.cpp: In function ‘std::eek:stream& operator<<(std::eek:stream&, const std::vector<T, std::allocator<_CharT> >&) [with T = int]’:
try.cpp:21: instantiated from here
try.cpp:12: error: no match for ‘operator=’ in ‘iter = ((const
std::vector<int, std::allocator<int> >*)vec)->std::vector<_Tp,
_Alloc>::begin [with _Tp = int, _Alloc = std::allocator<int>]()’

Have you tried:

typename vector<T>::const_iterator iter;

?


Ah thanks, it does work, but actually only if it's in the same file.
If it's in an external header (how I would like) it doesn't find...
So no way??
 
J

James Kanze

Larry Evans said:
On 11/09/10 18:13, Andrea Crotti wrote:
[snip]
I thought that something like this would be possible
template <typename T>
ostream& operator<<(ostream& s, const vector<T>& vec)
{
typename vector<T>::iterator iter;
for (iter=vec.begin(); iter!=vec.end(); ++iter) {
s << (*iter);
}
return s;
}
But actually I guess it's not, since then I don't know how
to pass the template parameter and I get this erro
try.cpp: In function ‘std::eek:stream& operator<<(std::eek:stream&, const std::vector<T, std::allocator<_CharT> >&) [with T = int]’:
try.cpp:21: instantiated from here
try.cpp:12: error: no match for ‘operator=’ in ‘iter = ((const
std::vector<int, std::allocator<int> >*)vec)->std::vector<_Tp,
_Alloc>::begin [with _Tp = int, _Alloc = std::allocator<int>]()’
Have you tried:
typename vector<T>::const_iterator iter;
?
Ah thanks, it does work, but actually only if it's in the same
file. If it's in an external header (how I would like) it
doesn't find... So no way??

There are several problems with this solution. The most obvious
is that it only compiles if the actual T and the operator<< are in
the same namespace. And doesn't compile at all if T is a basic
type like double, since these aren't in any namespace. (When
I say "doesn't compile", I mean with a conformant compiler.
It's possible, likely even, that some compilers still accept
it.) You can cheat, and put the operator<< in namespace std (so
the compiler will always find it with ADL): formally, this is
undefined behavior (but will almost certainly work), and
practically, it doesn't resolve the following problems.

Another obvious problem is that you have no separator, so when
outputting many types (e.g. double), the results are unreadable.
(If the results are to be read back in, and not just read by
a human, std::string may cause problems as well.)

A more fundamental problem is that such code is unmaintainable.
What happens if someone working on another module needs
something similar, but with a different separator? There is
a reason why things like this aren't in the standard.
 
Ad

Advertisements

A

Andrea Crotti

James Kanze said:
There are several problems with this solution. The most obvious
is that it only compiles if the actual T and the operator<< are in
the same namespace. And doesn't compile at all if T is a basic
type like double, since these aren't in any namespace. (When
I say "doesn't compile", I mean with a conformant compiler.
It's possible, likely even, that some compilers still accept
it.) You can cheat, and put the operator<< in namespace std (so
the compiler will always find it with ADL): formally, this is
undefined behavior (but will almost certainly work), and
practically, it doesn't resolve the following problems.

Another obvious problem is that you have no separator, so when
outputting many types (e.g. double), the results are unreadable.
(If the results are to be read back in, and not just read by
a human, std::string may cause problems as well.)

A more fundamental problem is that such code is unmaintainable.
What happens if someone working on another module needs
something similar, but with a different separator? There is
a reason why things like this aren't in the standard.

Ok I got it a very stupid idea ;-)
Thanks...
I don't want to cheat, adn actually those print are just for testing and
understanding, they would be completely useless in "production" since
nobody will "look at them".
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top