By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
446,170 Members | 1,053 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 446,170 IT Pros & Developers. It's quick & easy.

[VC++ 6.0] Ambiguous call to overloaded function

P: n/a
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

Jul 4 '06 #1
Share this Question
Share on Google+
5 Replies


P: n/a
* 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?
Jul 4 '06 #2

P: n/a
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

Jul 4 '06 #3

P: n/a
* 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?
Jul 4 '06 #4

P: n/a
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 :)

Jul 4 '06 #5

P: n/a
"rolandz" <ro*****@poczta.fmwrote in message
news:11**********************@p79g2000cwp.googlegr oups.com...
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.
Jul 4 '06 #6

This discussion thread is closed

Replies have been disabled for this discussion.