Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > error: ambiguous overload for 'operator <<' in...

Reply
Thread Tools

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

 
 
Marcus Kwok
Guest
Posts: n/a
 
      10-26-2006
glen <(E-Mail Removed)> 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:stream& operator<< (std: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.

--
Marcus Kwok
Replace 'invalid' with 'net' to reply
 
Reply With Quote
 
 
 
 
Steve Hicks
Guest
Posts: n/a
 
      10-26-2006
On Oct 26, 5:48 pm, glen <(E-Mail Removed)> wrote:
> template<typename C>
> std:stream& operator<< (std: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

 
Reply With Quote
 
 
 
 
Salt_Peter
Guest
Posts: n/a
 
      10-26-2006

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

 
Reply With Quote
 
Pete Becker
Guest
Posts: n/a
 
      10-26-2006
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:stream& operator<< (std:stream& 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.
 
Reply With Quote
 
Pete Becker
Guest
Posts: n/a
 
      10-26-2006
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.
 
Reply With Quote
 
Salt_Peter
Guest
Posts: n/a
 
      10-26-2006

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


 
Reply With Quote
 
glen
Guest
Posts: n/a
 
      10-26-2006
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:stream& operator<< (std: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

 
Reply With Quote
 
Pete Becker
Guest
Posts: n/a
 
      10-26-2006
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:stream& operator<< (std:stream& 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.
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Compilation error due to ambiguous overload when using enums withtemplates puzzlecracker C++ 1 01-27-2009 04:38 PM
ambiguous overload? highegg C++ 9 12-16-2008 06:57 AM
ambiguous overload when used with derived classes? sebastian C++ 9 05-26-2008 02:09 AM
ambiguous overload onkar C++ 11 01-08-2008 08:34 AM
How use the overload of>> (or<<) of a class in the overload of << and >> of another class? Piotre Ugrumov C++ 3 01-25-2004 08:08 PM



Advertisments