why standard convesion is picked instead of constructor conversion

T

tom

I have a code segment list below, for the function call "calc()" in
the main function, a standard conversion from "double"->"int" is made
while "double"->"LongDouble" is also viable, does anyone know why
standard conversion is picked as the best match by the compilier?

#include <iostream>

class LongDouble
{
public:
operator double() const
{
return 2.0;
}
};

void calc(int a)
{
std::cout<<"void calc(int a) called"<<std::endl;
}
void calc(LongDouble a)
{
std::cout<<"void calc(LongDouble a)"<<std::endl;
}

int main(int argc, char *argv[])
{
double dval = 0.0;
calc(dval);
return 0;
}
 
?

=?ISO-8859-1?Q?Erik_Wikstr=F6m?=

I have a code segment list below, for the function call "calc()" in
the main function, a standard conversion from "double"->"int" is made
while "double"->"LongDouble" is also viable, does anyone know why
standard conversion is picked as the best match by the compilier?

You've got it backwards, a conversion from LongDouble to duble is
possible but not the other way around. To make that conversion possible
you have to add a constructor taking a double to LongDouble.
 
T

tom

You've got it backwards, a conversion from LongDouble to duble is
possible but not the other way around. To make that conversion possible
you have to add a constructor taking a double to LongDouble.

Sorry, my mistake (in the double->LongDouble conversion, is should be
a constructor), my question is actually for the code below:

#include <iostream>
class LongDouble
{
public:
// double -> LongDouble conversion
LongDouble(double dval)
{
}
};

void calc(int a)
{
std::cout<<"void calc(int a) called"<<std::endl;
}

void calc(LongDouble a)
{
std::cout<<"void calc(LongDouble a)"<<std::endl;
}

int main(int argc, char *argv[])
{
double dval = 0.0;
calc(dval);
return 0;
}
 
G

Greg Herlihy

Sorry, my mistake (in the double->LongDouble conversion, is should be
a constructor), my question is actually for the code below:

#include <iostream>
class LongDouble
{
public:
// double -> LongDouble conversion
LongDouble(double dval)
{
}

};

void calc(int a)
{
std::cout<<"void calc(int a) called"<<std::endl;

}

void calc(LongDouble a)
{
std::cout<<"void calc(LongDouble a)"<<std::endl;

}

int main(int argc, char *argv[])
{
double dval = 0.0;
calc(dval);
return 0;

}

In this case, converting the double argument to an int parameter is
considered a "better" match than converting the double argument to a
LongDouble parameter. According to the C++ Standard, standard
conversions (like double-to-int) have a higher rank than user-defined
conversions (such as double-to-LongDouble).

This point can be tested by adding another calc() overload:

void calc( long double ld) // Error: ambiguous
{
}

With this addition, there are now two possible standard conversions
(int-to-double and double-to-long double), so there is no clear
favorite anymore and the call to calc() is now ambiguous.

The best approach is probably not to mix user-defined and built-in
types in this manner. I would either have the program use the "long
double" built-in type instead of a LongDouble user-defined type - or -
I would keep the LongDouble type and define an Integer type to go
along with it.

Greg
 
T

tom

Sorry, my mistake (in the double->LongDouble conversion, is should be
a constructor), my question is actually for the code below:
#include <iostream>
class LongDouble
{
public:
// double -> LongDouble conversion
LongDouble(double dval)
{
}

void calc(int a)
{
std::cout<<"void calc(int a) called"<<std::endl;

void calc(LongDouble a)
{
std::cout<<"void calc(LongDouble a)"<<std::endl;

int main(int argc, char *argv[])
{
double dval = 0.0;
calc(dval);
return 0;

In this case, converting the double argument to an int parameter is
considered a "better" match than converting the double argument to a
LongDouble parameter. According to the C++ Standard, standard
conversions (like double-to-int) have a higher rank than user-defined
conversions (such as double-to-LongDouble).

This point can be tested by adding another calc() overload:

void calc( long double ld) // Error: ambiguous
{
}

With this addition, there are now two possible standard conversions
(int-to-double and double-to-long double), so there is no clear
favorite anymore and the call to calc() is now ambiguous.

The best approach is probably not to mix user-defined and built-in
types in this manner. I would either have the program use the "long
double" built-in type instead of a LongDouble user-defined type - or -
I would keep the LongDouble type and define an Integer type to go
along with it.

Greg

Thanks for the reply and good advice.
 

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,769
Messages
2,569,581
Members
45,056
Latest member
GlycogenSupporthealth

Latest Threads

Top