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')
4
  • 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. Commented Aug 4, 2017 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. Commented Aug 4, 2017 at 12:11
  • @PeteBecker Good answer. Would you please post it instead of leaving it as a comment? Commented Aug 4, 2017 at 12:12
  • @NathanOliver I want 2 for the same effect as '\x02'. The value is borrowed from the question that I mentioned. Commented Aug 4, 2017 at 12:13

1 Answer 1

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.

Sign up to request clarification or add additional context in comments.

7 Comments

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 Thanks, added. Don't think that catching up will happen though, the answer is already too old for that. XD
Let me conclude: Data can't be implicitly cast if it's used for type deduction.
@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.)
@iBug But do note that the target type cannot be determined at all instead of not being determined yet.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.