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

M

Marcus Kwok

glen said:
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::eek:stream& operator<< (std::eek:stream& 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.
 
S

Steve Hicks

template<typename C>
std::eek:stream& operator<< (std::eek:stream& 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
 
S

Salt_Peter

glen said:
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::eek:stream& operator<< (std::eek:stream& 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::eek:stream& operator<< (std::eek:stream& 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::eek:stream&
operator<<(std::eek:stream& 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;
}
 
P

Pete Becker

Salt_Peter said:
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.
 
P

Pete Becker

glen said:
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.
 
S

Salt_Peter

Pete said:
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.
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.
 
G

glen

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::eek:stream& operator<< (std::eek:stream& 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
 
P

Pete Becker

Salt_Peter said:
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.
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.
 

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

Members online

No members online now.

Forum statistics

Threads
473,995
Messages
2,570,230
Members
46,819
Latest member
masterdaster

Latest Threads

Top