7

Someone asked this question about string appending. It's string s; s = s + 2; not compiling. People gave answers stating that operator+ is defined as a template function while operator+= is not, so auto downcasting (int(2) to char(2)) is not applied.

The prototypes are

template<typename _CharT, typename _Traits, typename _Alloc>
class basic_string{
    basic_string&
      operator+=(_CharT __c);
};

template<typename _CharT, typename _Traits, typename _Alloc>
  inline basic_string<_CharT, _Traits, _Alloc>
  operator+(const basic_string<_CharT, _Traits, _Alloc>& __lhs, _CharT __rhs);

Why can't the compiler just use this prototype and cast int(2) to char(2)?

basic_string<char, _T, _A> operator+(const basic_string<char, _T, _A>, char);

The compiler (G++ 6.3.0) complains that

[Note] deduced conflicting types for parameter '_CharT' ('char' and 'int')
iBug
  • 35,554
  • 7
  • 89
  • 134
  • 2
    The rule is that the compiler does not look at conversions when it is trying to infer template types; the types must match exactly. While there are cases where conversions could be convenient and straightforward, in general there are too many possibilities, and the compiler simply is not required to paw through every possible type in search for something that could be converted to something that might match part of the template argument list. – Pete Becker Aug 04 '17 at 12:08
  • It could be but it is not. Doing so would require the template to be specialized for all the standard types that `basic_string` is supposed to support. Also `string s; s = s + 2;` doesn't make much sense. Do you want the ascii character with the value of 2 or do you want `'2'`? I can't see why your would need you version. – NathanOliver Aug 04 '17 at 12:11
  • @PeteBecker Good answer. Would you please post it instead of leaving it as a comment? – iBug Aug 04 '17 at 12:12
  • @NathanOliver I want 2 for the same effect as '\x02'. The value is borrowed from the question that I mentioned. – iBug Aug 04 '17 at 12:13

1 Answers1

8

The key difference is that for the operator += variant, the char type template argument for the std::basic_string, and thus the argument type for its RHS, is already fixed to char, while the operator+ template has to deduce that from its arguments.

Thus, for the += case, the compiler knows you "want" the int->char conversion, there is nothing to deduce there.

For the operator+ case on the other hand, the compiler is looking at the template

template<class CharT, class Traits, class Alloc>
    basic_string<CharT,Traits,Alloc>
        operator+( const basic_string<CharT,Traits,Alloc>& lhs,
                   CharT rhs );

and, when trying to determine what CharT is supposed to be, it gets CharT = char from the first operand (as std::string is std::basic_string<char>) and CharT = int from the second operand. Such a conflict is defined to be a compilation error by the standard.

Baum mit Augen
  • 49,044
  • 25
  • 144
  • 182
  • Upvoted. This is much better than my answer in the linked question, and the voting needs to catch up. (As icing on the cake, you might want to mention the relationship between `CharT` and `char`.) – Bathsheba Aug 04 '17 at 12:37
  • @Bathsheba Thanks, added. Don't think that catching up will happen though, the answer is already too old for that. XD – Baum mit Augen Aug 04 '17 at 12:45
  • Let me conclude: **Data can't be implicitly cast if it's used for type deduction**. – iBug Aug 09 '17 at 10:54
  • @iBug In informal terms that's right in some sense. (Formally, there is no cast, those are always explicit. There would be an implicit conversion, but that can only happen *after* some target type is determined, and that step fails already due to the aforementioned ambiguity.) – Baum mit Augen Aug 09 '17 at 10:57
  • So do you mean there's nothing to cast because *at the time when I want the **implicit** cast to happen, the target type hasn't been determined*? – iBug Aug 09 '17 at 11:05
  • @iBug Conversion instead of cast, but basically yes. The compiler cannot even figure out what conversion you would like to see. If you actually *do* cast to the right type, the code compiles. Like `string s; s = s + char(2);` – Baum mit Augen Aug 09 '17 at 11:08
  • 1
    @iBug But do note that the target type cannot be determined at all instead of not being determined yet. – Baum mit Augen Aug 09 '17 at 11:14