468,771 Members | 1,763 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 468,771 developers. It's quick & easy.

error: ambiguous overload for 'operator <<' in...

Hi. I'm using GCC 4.1.1, which I mention since I don't know
if this is a compiler issue, or me not understanding some
subtlety in the standard.

The code below compiles fine under vc++, but I'm having trouble
using gcc. It's just a templated container output.
/**
outputs elements of a vector in the form '{el1,el2...elEnd}'
*/
template<typename C>
std::ostream& operator<< (std::ostream& op, const C& cpi )
{
typename C::const_iterator start( cpi.begin() ); typename
C::const_iterator end( --(cpi.end() )); typename C::const_iterator iter;
op << "{";
for (iter=start;iter!=end; ++iter){
op<<*iter<<",";
}
op<<*iter<<"}";
return op;
};

The offending lines are the
op<<"{";
and
op<<"}";

apparently it doesn't know what to do with a simple string, but it can
handle the template argument...

So am I on topic here, and if so can someone please give me a little
insight? I appreciate any assistance that can be given. Searched the web
but was unable to find anything that helped (I also posted to a g++ group).

Glen

Oct 26 '06 #1
7 13831
glen <st***@ife.ee.ethz.chwrote:
Hi. I'm using GCC 4.1.1, which I mention since I don't know
if this is a compiler issue, or me not understanding some
subtlety in the standard.

The code below compiles fine under vc++, but I'm having trouble
using gcc. It's just a templated container output.
/**
outputs elements of a vector in the form '{el1,el2...elEnd}'
*/
template<typename C>
std::ostream& operator<< (std::ostream& op, const C& cpi )
{
typename C::const_iterator start( cpi.begin() ); typename
C::const_iterator end( --(cpi.end() )); typename C::const_iterator iter;
op << "{";
for (iter=start;iter!=end; ++iter){
op<<*iter<<",";
}
op<<*iter<<"}";
return op;
};

The offending lines are the
op<<"{";
and
op<<"}";

apparently it doesn't know what to do with a simple string, but it can
handle the template argument...

So am I on topic here, and if so can someone please give me a little
insight? I appreciate any assistance that can be given. Searched the web
but was unable to find anything that helped (I also posted to a g++ group).
AFAIK operator<< for a const char* should be available. Since it's only
a single character, maybe you could try

op << '{';

instead.

Another is to double-check that you have all the necessary #includes.
Maybe the Standard Library of VC++ implicitly includes something that
gcc does not. Also, make sure you are using g++ instead of gcc.

--
Marcus Kwok
Replace 'invalid' with 'net' to reply
Oct 26 '06 #2
On Oct 26, 5:48 pm, glen <s...@ife.ee.ethz.chwrote:
template<typename C>
std::ostream& operator<< (std::ostream& op, const C& cpi )
{
typename C::const_iterator start( cpi.begin() ); typename
C::const_iterator end( --(cpi.end() )); typename C::const_iterator iter;
op << "{";
for (iter=start;iter!=end; ++iter){
op<<*iter<<",";
}
op<<*iter<<"}";
return op;
};

The offending lines are the
op<<"{";
and
op<<"}";
I'm not terribly sure about some of the subtleties here, but I think it
has something to do with the generality of your overload. Maybe "{"
can be implictly cast to a const std::string &, which fits your
template also, but already has its own overloaded operator<< - so which
overload to use is ambiguous.

-steve

Oct 26 '06 #3

glen wrote:
Hi. I'm using GCC 4.1.1, which I mention since I don't know
if this is a compiler issue, or me not understanding some
subtlety in the standard.

The code below compiles fine under vc++, but I'm having trouble
using gcc. It's just a templated container output.
/**
outputs elements of a vector in the form '{el1,el2...elEnd}'
*/
template<typename C>
std::ostream& operator<< (std::ostream& op, const C& cpi )
type C is not a container, its just a const type (an element). If you
meant to pass a std::vector by reference:

template< typename C >
std::ostream& operator<< (std::ostream& os, const std::vector< C >& r_v
)
{
... // iterate through the container's elements
}
{
typename C::const_iterator start( cpi.begin() ); typename
C::const_iterator end( --(cpi.end() )); typename C::const_iterator iter;
op << "{";
for (iter=start;iter!=end; ++iter){
op<<*iter<<",";
}
op<<*iter<<"}";
return op;
};

The offending lines are the
op<<"{";
and
op<<"}";
#include <iostream>
#include <ostream>
#include <string>
#include <vector>
#include <iterator>

template< typename T >
std::ostream&
operator<<(std::ostream& os, const std::vector< T >& r_vc )
{
typedef typename std::vector< T >::const_iterator VIter;
VIter viter = r_vc.begin();
while (viter != r_vc.end())
{
os << "{ " << *viter++;
os << " }\n";
}
return os;
}

int main()
{
std::vector< std::string vs;
vs.push_back("string_0");
vs.push_back("string_1");
vs.push_back("string_2");

std::vector< double vd;
vd.push_back( 0.0 );
vd.push_back( 1.1 );
vd.push_back( 2.2 );

std::vector< char vc;
vc.push_back('a');
vc.push_back('b');
vc.push_back('c');

std::cout << vs << vd << vc;

return 0;
}

Oct 26 '06 #4
Salt_Peter wrote:
glen wrote:
>Hi. I'm using GCC 4.1.1, which I mention since I don't know
if this is a compiler issue, or me not understanding some
subtlety in the standard.

The code below compiles fine under vc++, but I'm having trouble
using gcc. It's just a templated container output.
/**
outputs elements of a vector in the form '{el1,el2...elEnd}'
*/
template<typename C>
std::ostream& operator<< (std::ostream& op, const C& cpi )

type C is not a container, its just a const type (an element).
If you call this inserter with a vector then C is a vector.
while (viter != r_vc.end())
{
os << "{ " << *viter++;
os << " }\n";
}
The formatting that this code does is rather different from what the
orignal code does. It precedes every element with a {, while the
original code put one { at the beginning and separated each pair of
elements with a comma. It skips the tricky part.<g>

--

-- Pete

Author of "The Standard C++ Library Extensions: a Tutorial and
Reference." For more information about this book, see
www.petebecker.com/tr1book.
Oct 26 '06 #5
glen wrote:
>
So am I on topic here, and if so can someone please give me a little
insight? I appreciate any assistance that can be given. Searched the web
but was unable to find anything that helped (I also posted to a g++ group).
Marcus's second answer is probably right: the code which you didn't show
doesn't have all of the necessary includes. I'd guess that it doesn't
pull in <ostream>.

Also, the code can be more general if it doesn't try so hard to avoid an
extra test. Instead of looping up to --cpi.end(), which won't compile
for an input iterator or a forward iterator and might not work with an
empty container, just write out the first element, then for each
subsequent element write a comma and the element. Like this:

op << "{";
if (iter != cpi.end())
op << *iter++;
while (iter != cpi.end())
op << "," << *iter++;
op << "}";

I'd use single chars in all three places instead of those quoted
strings, because it's faster, but that doesn't affect the validity of
the code. If you're going to do that, though, wait until you've figured
out why the version with the quoted strings doesn't compile.

--

-- Pete

Author of "The Standard C++ Library Extensions: a Tutorial and
Reference." For more information about this book, see
www.petebecker.com/tr1book.
Oct 26 '06 #6

Pete Becker wrote:
Salt_Peter wrote:
glen wrote:
Hi. I'm using GCC 4.1.1, which I mention since I don't know
if this is a compiler issue, or me not understanding some
subtlety in the standard.

The code below compiles fine under vc++, but I'm having trouble
using gcc. It's just a templated container output.
/**
outputs elements of a vector in the form '{el1,el2...elEnd}'
*/
template<typename C>
std::ostream& operator<< (std::ostream& op, const C& cpi )
type C is not a container, its just a const type (an element).

If you call this inserter with a vector then C is a vector.
Thats fundamentally wrong.
The compiler will attempt to regenerated a new version of op<< every
time that
cout << whatever;
or
os << whatever;
or
os << " ";
is found in the underlying code.
error: ambiguous overload for 'operator<<' is your result.
>
while (viter != r_vc.end())
{
os << "{ " << *viter++;
os << " }\n";
}

The formatting that this code does is rather different from what the
orignal code does. It precedes every element with a {, while the
original code put one { at the beginning and separated each pair of
elements with a comma. It skips the tricky part.<g>
Granted, the coder can adapt the output to whatever he needs.
>
--

-- Pete

Author of "The Standard C++ Library Extensions: a Tutorial and
Reference." For more information about this book, see
www.petebecker.com/tr1book.
Oct 26 '06 #7
Salt_Peter wrote:
Pete Becker wrote:
>Salt_Peter wrote:
>>glen wrote:
Hi. I'm using GCC 4.1.1, which I mention since I don't know
if this is a compiler issue, or me not understanding some
subtlety in the standard.

The code below compiles fine under vc++, but I'm having trouble
using gcc. It's just a templated container output.
/**
outputs elements of a vector in the form '{el1,el2...elEnd}'
*/
template<typename C>
std::ostream& operator<< (std::ostream& op, const C& cpi )
type C is not a container, its just a const type (an element).
If you call this inserter with a vector then C is a vector.

Thats fundamentally wrong.
No, it's absolutely correct.
The compiler will attempt to regenerated a new version of op<< every
time that
cout << whatever;
or
os << whatever;
or
os << " ";
is found in the underlying code.
error: ambiguous overload for 'operator<<' is your result.
For overloading, template specializations are ordered, and the most
specific one wins.
>
>> while (viter != r_vc.end())
{
os << "{ " << *viter++;
os << " }\n";
}
The formatting that this code does is rather different from what the
orignal code does. It precedes every element with a {, while the
original code put one { at the beginning and separated each pair of
elements with a comma. It skips the tricky part.<g>

Granted, the coder can adapt the output to whatever he needs.
Well, sure. But this doesn't address the problem he asked about.

--

-- Pete

Author of "The Standard C++ Library Extensions: a Tutorial and
Reference." For more information about this book, see
www.petebecker.com/tr1book.
Oct 26 '06 #8

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

7 posts views Thread by Piotre Ugrumov | last post: by
25 posts views Thread by Steve Richter | last post: by
2 posts views Thread by Harry | last post: by
11 posts views Thread by fungus | last post: by
5 posts views Thread by David | last post: by
1 post views Thread by CARIGAR | last post: by
reply views Thread by zhoujie | last post: by
1 post views Thread by Marin | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.