Why does the following lead to failed overload resolution?
#include <iostream>
using namespace std;
void print( char c ) { cout << "Char\n"; }
void print( float f ) { cout << "Float\n"; }
int main(){
print( 'a' );
print( 1.23 );
}
Recall that the floating-point literal is a double
by default.
Q1: When I replace 1.23
by 1.23f
, then the overload resolution works. What is the relevant difference between 1.23
and 1.23f
in this context?
Q2: Even more shocking, if I remove print( float f )
, the code compiles. Why can a floating-point literal be cast to a char?
Q3: Are there at least compiler warnings that notice such (almost surely unintentional) conversions?
I presume this behavior in C is inherited from C, and that it is an instance of floating-point-to-integral conversion.
CodePudding user response:
What is the relevant difference between 1.23 and 1.23f
1.23
has type double
, 1.23f
has type float
.
Why can a floating-point literal be cast to a char?
char
is an integer type, has (at-least) 8-bits. Just like int a = 1.23;
is converting 1.23
to int
, the same does char c = 1.23
, it's the same conversion, just char
is (should be) smaller than int
. It's a normal integer, just small.
Are there at least compiler warnings that notice such (almost surely unintentional) conversions?
-Wconversion
on GCC.
source:6:8: warning: conversion from ‘double’ to ‘char’ changes value from ‘1.23e 0’ to ‘'\001'’ [-Wfloat-conversion]
6 | print( 1.23 );
| ^~~~
CodePudding user response:
The 'ranks' used for overload resolution are, in order:
- Exact match
- Promotion
- Conversion
In the case of your call to the print
function with a double
argument, neither (1) nor (2) apply; further, when converting from the given double
, there is no defined 'preference' or rank for choosing between converting to a float
or to an integral type (char
, in your case). Thus, the attempted overload resoultion is ambiguous.
What would be different is if you were to declare your second overload to take a double
argument and then make a call with an explicit 1.23f
(i.e. float
) argument; in that case, floating-point promotion would kick-in (ranking above conversion) and there would be no ambiguity.