Home > Blockchain >  Why can a floating-point literal be cast to a char in C in this overload resolution error?
Why can a floating-point literal be cast to a char in C in this overload resolution error?

Time:02-15

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:

  1. Exact match
  2. Promotion
  3. 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.

  •  Tags:  
  • c
  • Related