Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does g++ not warn/err while concatenating an integer to a string using +=

I have this code:

#include <iostream>                     
using namespace std; 

int main()                  
{                                                                                    
       string name = "John ";                     
       int age = 32;         
       name += age;    
       cout << name << endl;
       return 0;                                          
}

The code compiles successfully but betrays at run time as it silently ignores the concatenation part and prints:

John

I know that we need to use stringstream for the task. But why does the above code compile? Because the following code:

#include <iostream>
using namespace std;                                                                 

int main()                       
{                                                                                    
       string name = "John ";                              
       int age = 55;                                    
       name = name + age;             
       cout << name << endl;      
       return 0;
} 

duly throws and error:

error: no match for ‘operator+’ in ‘name + age’

I know from Java that a += b is different from a = a + b as the former construct typecasts the result to the type of a. Reference. But I don't think this would matter in C++ as we can always do:

   int a = 1;                                                                       
   float f = 3.33;                                                                  
   a = a + f;

without worrying about a possible loss of precision warning unlike Java. Need citation for this in C++.

So now if we assume that name += age; expands to name = string (name + age); then also the code should not have compiled simply because name + age is not legal.

like image 847
KodingKid Avatar asked Dec 20 '22 20:12

KodingKid


1 Answers

You need to use the -Wconversion flag(It is not clear to me why this is not included in -Wall) also see the Options to Request or Suppress Warnings for more details. When I add that flag I see the following warning when using gcc:

 warning: conversion to 'char' from 'int' may alter its value [-Wconversion]
    name += age;  
         ^

and we can see that indeed operator += does support char and therefore the converted value is indeed being add to the end of name, it is not ignoring the operation at all. In C++ operator + for std::string is a different operator than operator +=.

In this specific case:

name += age;

would translate to something like this:

name.operator+=(static_cast<char>(age)) ;

and if we had a expression using operator + without an error like this one:

name = name + static_cast<char>( age );

would translate to:

operator+( name, static_cast<char>( age ) ) ;

The reason why this fails for operator + in your example is covered well in this answer, basically template functions won't perform conversions and so require an exact match with the possible exception of const/volatile qualifiers.

Update on Wconversion

gcc has a Wconversion Wiki with a FAQ, it is a bit dated but it does answer why this check is not included with the -Wall flag:

Implicit conversions are very common in C. This tied with the fact that there is no data-flow in front-ends (see next question) results in hard to avoid warnings for perfectly working and valid code. Wconversion is designed for a niche of uses (security audits, porting 32 bit code to 64 bit, etc.) where the programmer is willing to accept and workaround invalid warnings. Therefore, it shouldn't be enabled if it is not explicitly requested.

like image 126
Shafik Yaghmour Avatar answered Dec 22 '22 11:12

Shafik Yaghmour