Why isn't automatic downcasting applied to template functions?
Asked Answered
S

1

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')
Saunders answered 4/8, 2017 at 12:3 Comment(4)
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.Meleager
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.Jakie
@PeteBecker Good answer. Would you please post it instead of leaving it as a comment?Saunders
@Jakie I want 2 for the same effect as '\x02'. The value is borrowed from the question that I mentioned.Saunders
I
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.

Insistency answered 4/8, 2017 at 12:14 Comment(7)
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.)Numerate
@Numerate Thanks, added. Don't think that catching up will happen though, the answer is already too old for that. XDInsistency
Let me conclude: Data can't be implicitly cast if it's used for type deduction.Saunders
@Saunders 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.)Insistency
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?Saunders
@Saunders 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);Insistency
@Saunders But do note that the target type cannot be determined at all instead of not being determined yet.Insistency

© 2022 - 2024 — McMap. All rights reserved.