[VC++ 6.0] Ambiguous call to overloaded function

Discussion in 'C++' started by rolandz, Jul 4, 2006.

  1. rolandz

    rolandz Guest

    Hi,

    Maybe somebody has been fighting with the problem that I do, currently.
    I have a class that has method f(). The two versions of the f() method
    accept different objects: Int and Short. These objects have
    constructors that allow implicit conversions from simple types. All
    this has been defined as follows:

    <code>
    class Int
    {
    public:
    Int(const int);
    };

    class Short
    {
    public:
    Short(const short);
    };

    class AClass
    {
    public:
    void f(const Int &);
    void f(const Short &);
    };
    </code>

    Further, in the code, I have a following invocation:

    <code>

    AClass().f( 1 ); // <--- It is important that the type is int here!

    </code>

    But the compiler (VC++ 6.0) says:
    error C2668: 'f' : ambiguous call to overloaded function

    My question is why? Do I understand C++ implicit type conversion
    imcorrectly or M$ makes sbth wrong?

    TIA

    --
    Roland
     
    rolandz, Jul 4, 2006
    #1
    1. Advertising

  2. * rolandz:
    > Hi,
    >
    > Maybe somebody has been fighting with the problem that I do, currently.
    > I have a class that has method f(). The two versions of the f() method
    > accept different objects: Int and Short. These objects have
    > constructors that allow implicit conversions from simple types. All
    > this has been defined as follows:
    >
    > <code>
    > class Int
    > {
    > public:
    > Int(const int);
    > };
    >
    > class Short
    > {
    > public:
    > Short(const short);
    > };
    >
    > class AClass
    > {
    > public:
    > void f(const Int &);
    > void f(const Short &);
    > };
    > </code>
    >
    > Further, in the code, I have a following invocation:
    >
    > <code>
    >
    > AClass().f( 1 ); // <--- It is important that the type is int here!
    >
    > </code>
    >
    > But the compiler (VC++ 6.0) says:
    > error C2668: 'f' : ambiguous call to overloaded function
    >
    > My question is why?


    Either choice of function to call involves one user-defined conversion.


    > Do I understand C++ implicit type conversion
    > imcorrectly


    Probably.


    > or M$ makes sbth wrong?


    Probably... ;-) But not here.

    You can write

    AClass.f( Int( 1 ) );

    to disambiguate.

    --
    A: Because it messes up the order in which people normally read text.
    Q: Why is it such a bad thing?
    A: Top-posting.
    Q: What is the most annoying thing on usenet and in e-mail?
     
    Alf P. Steinbach, Jul 4, 2006
    #2
    1. Advertising

  3. rolandz

    rolandz Guest

    Alf P. Steinbach napisal(a):

    > > Maybe somebody has been fighting with the problem that I do, currently.
    > > I have a class that has method f(). The two versions of the f() method
    > > accept different objects: Int and Short. These objects have
    > > constructors that allow implicit conversions from simple types. All
    > > this has been defined as follows:
    > >
    > > <code>
    > > class Int
    > > {
    > > public:
    > > Int(const int);
    > > };
    > >
    > > class Short
    > > {
    > > public:
    > > Short(const short);
    > > };
    > >
    > > class AClass
    > > {
    > > public:
    > > void f(const Int &);
    > > void f(const Short &);
    > > };
    > > </code>
    > >
    > > Further, in the code, I have a following invocation:
    > >
    > > <code>
    > >
    > > AClass().f( 1 ); // <--- It is important that the type is int here!
    > >
    > > </code>
    > >
    > > But the compiler (VC++ 6.0) says:
    > > error C2668: 'f' : ambiguous call to overloaded function
    > >
    > > My question is why?


    > You can write


    > AClass.f( Int( 1 ) );


    This is exactly what I do not want to do... I want it to be transparent
    for a user. The purpose is to provide a way to collect parameters in
    some internal array of pointers in the AClass. But the parameters MUST
    be allocated on stack (not heap) for performance reason.

    The Int and Short classes are ment to be such wrappers on simple types
    that are being allocated on stack. The conversion was designed for
    transparent conversion so user even does not neet to know it.

    --
    Roland
     
    rolandz, Jul 4, 2006
    #3
  4. * rolandz:
    > Alf P. Steinbach napisal(a):
    >
    >> You can write

    >
    >> AClass.f( Int( 1 ) );

    >
    > This is exactly what I do not want to do... I want it to be transparent
    > for a user. The purpose is to provide a way to collect parameters in
    > some internal array of pointers in the AClass. But the parameters MUST
    > be allocated on stack (not heap) for performance reason.
    >
    > The Int and Short classes are ment to be such wrappers on simple types
    > that are being allocated on stack. The conversion was designed for
    > transparent conversion so user even does not neet to know it.


    That doesn't make much sense.

    Most probably you have a case of Premature Optimization, where every
    which way you're turning the language rules seem to try to stop you
    (because they're designed for meaningful code).

    Perhaps post a small program that compiles and illustrates what you're
    trying to do.

    --
    A: Because it messes up the order in which people normally read text.
    Q: Why is it such a bad thing?
    A: Top-posting.

    Q: What is the most annoying thing on usenet and in e-mail?
     
    Alf P. Steinbach, Jul 4, 2006
    #4
  5. rolandz

    rolandz Guest

    Alf P. Steinbach napisal(a):
    > > The Int and Short classes are ment to be such wrappers on simple types
    > > that are being allocated on stack. The conversion was designed for
    > > transparent conversion so user even does not neet to know it.

    >
    > That doesn't make much sense.
    >
    > Most probably you have a case of Premature Optimization, where every
    > which way you're turning the language rules seem to try to stop you
    > (because they're designed for meaningful code).
    >
    > Perhaps post a small program that compiles and illustrates what you're
    > trying to do.


    There are plenty of files, classes and interfaces. Following are the
    most close to the problem, I think:

    <code file="Operators.h">
    Core::ILogMessage & operator << (Core::ILogMessage & msg,
    const Impl::Serialization::ValueType::Byte & value);


    Core::ILogMessage & operator << (Core::ILogMessage & msg,
    const Impl::Serialization::ValueType::Int16 & value);


    Core::ILogMessage & operator << (Core::ILogMessage & msg,
    const Impl::Serialization::ValueType::Int32 & value);


    Core::ILogMessage & operator << (Core::ILogMessage & msg,
    const Impl::Serialization::ValueType::String & value);


    Core::ILogMessage & operator << (Core::ILogMessage & msg,
    const Impl::Serialization::ValueType::UInt16 & value);


    Core::ILogMessage & operator << (Core::ILogMessage & msg,
    const Impl::Serialization::ValueType::UInt32 & value);
    </code>

    There are more operators for more types - I've removed them from an
    example...

    <code file="Operators.cpp">
    Core::ILogMessage & operator << (Core::ILogMessage & msg,
    const Impl::Serialization::ValueType::Int16 & value)
    {
    msg.add(value);
    return msg;
    }


    Core::ILogMessage & operator << (Core::ILogMessage & msg,
    const Impl::Serialization::ValueType::Int32 & value)
    {
    msg.add(value);
    return msg;
    }
    </code>

    <code file="ILogMessage.h">
    namespace Core
    {
    class ILogMessage : virtual public Core::Serialization::ISerializable
    {
    public:
    virtual void add(const Core::Serialization::ISerializable & obj) = 0;

    };
    }
    </code>

    <code file="Int16.h">
    namespace Impl
    {
    namespace Serialization
    {
    namespace ValueType
    {
    class Int16 : public Core::Serialization::ISerializable
    {
    short value;

    public:
    Int16(const short _value);

    // Serializes object's data into a given stream
    void serialize(Core::Serialization::IWriteStream *stream) const;

    // Deserializes all object's data from a given stream
    void deserialize(Core::Serialization::IReadStream *stream);
    };
    }
    }
    }
    </code>

    <code file="Int32.h>
    namespace Impl
    {
    namespace Serialization
    {
    namespace ValueType
    {
    class Int32 : public Core::Serialization::ISerializable
    {
    long value;

    public:
    Int32(int _value);

    // Serializes object's data into a given stream
    void serialize(Core::Serialization::IWriteStream *stream) const;

    // Deserializes all object's data from a given stream
    void deserialize(Core::Serialization::IReadStream *stream);
    };
    }
    }
    }
    </code>

    There are also other types being defined identically as follows:

    Byte - unsigned char
    String - char *
    UInt16 - unsigned short
    UInt32 - unsigned long

    Then I have a main file with following code:
    <code file="Main.cpp">
    Core::ILog * log = Impl::LogManager::get()->getLog("main");
    for(unsigned long i = 0; i < 10000; ++i)
    {
    log->addLogEntry(Impl::Critical, &(Impl::Msg::ErrorMsg("Error %i, %s")
    << i )); // <=== There MUST be conversion.
    }
    </code>

    Let me clarify the add() method in the ILogMessage interface
    implementation that exists in the project. It stores passed parametes
    as a pointer in the internal array of ISerializable pointers. Because
    there is a constraint in the ILog interface implementation that stops
    processing if the logging level is insufficient at the moment. Thus I
    don't want to make any other activity than just temporarily store
    passed arguments. They will be used if necessary.

    Why on the stack? Because addLogEntry() method is to be invoked
    extreamly often and operator new() introduces too much cost for
    managing the arguments as well as it wuld introduce high heap
    fragmentation.

    If this description is insufficient for you I can prepare some small
    demo project but it might cost some effort I want to avoid :|

    Thanks for your attention :)
     
    rolandz, Jul 4, 2006
    #5
  6. rolandz

    Jim Langston Guest

    "rolandz" <> wrote in message
    news:...
    > Hi,
    >
    > Maybe somebody has been fighting with the problem that I do, currently.
    > I have a class that has method f(). The two versions of the f() method
    > accept different objects: Int and Short. These objects have
    > constructors that allow implicit conversions from simple types. All
    > this has been defined as follows:
    >
    > <code>
    > class Int
    > {
    > public:
    > Int(const int);
    > };
    >
    > class Short
    > {
    > public:
    > Short(const short);
    > };
    >
    > class AClass
    > {
    > public:
    > void f(const Int &);
    > void f(const Short &);
    > };
    > </code>
    >
    > Further, in the code, I have a following invocation:
    >
    > <code>
    >
    > AClass().f( 1 ); // <--- It is important that the type is int here!
    >
    > </code>
    >
    > But the compiler (VC++ 6.0) says:
    > error C2668: 'f' : ambiguous call to overloaded function
    >
    > My question is why? Do I understand C++ implicit type conversion
    > imcorrectly or M$ makes sbth wrong?
    >
    > TIA


    Your problem is that the compiler can not determine what you mean by "1".
    Is that an integer or a short? With floating point it's easier, it defaults
    to double unless you add f at the end. I'm not even sure if it would have
    trouble trying to determine if it wasn't a char value or not (I may test to
    find out).

    Your function should work for *non constants* because then it knows the type
    it's declared as.

    How to solve this? Well, this is a good reason for the rule "no magic
    numbers". I don't know if there is a solution you would be happy with using
    constants.
     
    Jim Langston, Jul 4, 2006
    #6
    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. ishekara

    ambiguous call to overloaded

    ishekara, Feb 25, 2005, in forum: C++
    Replies:
    7
    Views:
    6,582
    red floyd
    Feb 25, 2005
  2. , India
    Replies:
    1
    Views:
    424
    Kai-Uwe Bux
    Sep 10, 2007
  3. Joseph Turian

    Ambiguous call to overloaded function

    Joseph Turian, Dec 20, 2007, in forum: C++
    Replies:
    4
    Views:
    557
    tragomaskhalos
    Dec 20, 2007
  4. vinay.muthyal
    Replies:
    0
    Views:
    486
    vinay.muthyal
    Feb 26, 2008
  5. Ruki
    Replies:
    1
    Views:
    746
Loading...

Share This Page