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

Discussion in 'C++' started by Marcus Kwok, Oct 26, 2006.

  1. Marcus Kwok

    Marcus Kwok Guest

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

    --
    Marcus Kwok
    Replace 'invalid' with 'net' to reply
    Marcus Kwok, Oct 26, 2006
    #1
    1. Advertising

  2. Marcus Kwok

    Steve Hicks Guest

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

    On Oct 26, 5:48 pm, glen <> wrote:
    > 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
    Steve Hicks, Oct 26, 2006
    #2
    1. Advertising

  3. Marcus Kwok

    Salt_Peter Guest

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

    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::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;
    }
    Salt_Peter, Oct 26, 2006
    #3
  4. Marcus Kwok

    Pete Becker Guest

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

    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::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 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.
    Pete Becker, Oct 26, 2006
    #4
  5. Marcus Kwok

    Pete Becker Guest

    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.
    Pete Becker, Oct 26, 2006
    #5
  6. Marcus Kwok

    Salt_Peter Guest

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

    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::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 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.
    Salt_Peter, Oct 26, 2006
    #6
  7. Marcus Kwok

    glen Guest

    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
    glen, Oct 26, 2006
    #7
  8. Marcus Kwok

    Pete Becker Guest

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

    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::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 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.
    Pete Becker, Oct 26, 2006
    #8
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Alex Vinokur
    Replies:
    4
    Views:
    3,032
    Peter Koch Larsen
    Nov 26, 2004
  2. Tim Clacy
    Replies:
    15
    Views:
    2,661
    Kanenas
    May 30, 2005
  3. onkar

    ambiguous overload

    onkar, Jan 7, 2008, in forum: C++
    Replies:
    11
    Views:
    733
    James Kanze
    Jan 8, 2008
  4. puzzlecracker
    Replies:
    1
    Views:
    958
    puzzlecracker
    Jan 27, 2009
  5. Ying-Chieh Liao

    function overload (not operator overload)

    Ying-Chieh Liao, Oct 11, 2004, in forum: Perl Misc
    Replies:
    3
    Views:
    236
    Sherm Pendley
    Oct 11, 2004
Loading...

Share This Page