3

I've used cpp for quite a while, I was known that we cannot add string and numbers(as + operator is not overloaded for that). But , I saw a code like this.

#include <iostream>
using namespace std;
int main() {
    string a = "";
    a += 97;
    cout << a;
}

this outputs 'a' and I also tried this.

string a ="";
a=a+97;

The second code gives a compilation error(as invalid args to + operator, std::string and int). I don't want to concatenate the string and number. What is the difference? Why does one work but not the other?

I was expecting that a+=97 is the same as a=a+97 but it appears to be different.

Ted Lyngmo
  • 93,841
  • 5
  • 60
  • 108
Nakul Gopal
  • 60
  • 1
  • 4

1 Answers1

7

The first snippet works because std::string overrides operator+= to append a character to a string. 97 is the ASCII code for 'a', so the result is "a".

The second snippet does not work because there is no + operator defined that accepts a std::string and an int, and no conversion constructor to make a std::string out of an int or char. There two overloads of the + operator that take a char, but the compiler cannot tell which one to use. The match is ambiguous, so an error is reported.

Fred Larson
  • 60,987
  • 18
  • 112
  • 174
  • 2
    Shouldn't overload 3 of [`operator+`](https://en.cppreference.com/w/cpp/string/basic_string/operator+) take a `char` as second argument? But I guess it doesn't work, because `97` is an `int` and no `char`? – Lukas-T Aug 02 '21 at 14:11
  • 1
    @churill: Ah yes, you're correct. But the compiler cannot select that because it's not an unambiguous match. I'll update. – Fred Larson Aug 02 '21 at 14:13
  • 1
    `a = a + char(97);` would be a workaround. – Ted Lyngmo Aug 02 '21 at 14:16
  • Hmm, but `std::string::operator+=()` is also overloaded for `char*`. So why no ambiguity there? I'm not sure I have this completely correct yet. – Fred Larson Aug 02 '21 at 14:18
  • @FredLarson There's no `char*`? – Ted Lyngmo Aug 02 '21 at 14:19
  • @TedLyngmo: Overload 3 of `operator+=()` is `constexpr basic_string& operator+=( const CharT* s );` – Fred Larson Aug 02 '21 at 14:21
  • @FredLarson Yes, I mean, there is no `char*` in OP:s code. Perhaps I misunderstood. – Ted Lyngmo Aug 02 '21 at 14:22
  • @TedLyngmo: My premise was that there was ambiguity whether to convert the `int` to a `char` or a `char*`, but both operators have overloads for both. So now I'm doubting myself. – Fred Larson Aug 02 '21 at 14:23
  • 1
    @FredLarson `int` to `char*` won't happen implicitly. – Ted Lyngmo Aug 02 '21 at 14:24
  • @TedLyngmo: So I bet there's a different overload that's ambiguous in the `operator+()` case. – Fred Larson Aug 02 '21 at 14:25
  • @FredLarson No, it's not ambiguity. It's that the template parameter doesn't match so it can't find _any_ overload (if I'm not confusing myself here :-)). – Ted Lyngmo Aug 02 '21 at 14:29
  • @TedLyngmo: I'm looking over the template vomit. I get mostly "mismatched types", but for two overloads I get "deduced conflicting types". Trying to understand the overloads in question. – Fred Larson Aug 02 '21 at 14:31
  • @FredLarson :-) Yeah, I was looking at [`clang++`'s output](https://godbolt.org/z/d5od5TPrM) – Ted Lyngmo Aug 02 '21 at 14:33
  • @TedLyngmo: Yes, clang shows the same thing as my g++. The conflict seems to be between the const reference overload and the rvalue reference overload. Fascinating. – Fred Larson Aug 02 '21 at 14:40