Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can't the compiler use the std::string conversion function of the class when perform operator<<?

Consider the following struct with a user-defined conversion function that can convert itself to const char*;

struct S {
  operator const char*() { return "hello"; }
};

This work with <iostream>, we can print the struct S with no error message:

std::cout << S{} << '\n';

But if I change the return type to std::string:

struct S {
  operator std::string() { return "hello"; }
};

I got this compiler error message:

<source>:11:13: error: no match for 'operator<<' (operand types are 'std::ostream' {aka 'std::basic_ostream<char>'} and 'S')
11 |   std::cout << S{} << '\n';
   |   ~~~~~~~~~ ^~ ~~~
   |        |       |
   |        |       S
   |        std::ostream {aka std::basic_ostream<char>}
    <source>:11:18: note:   'S' is not derived from 'const std::__cxx11::basic_string<_CharT, _Traits, _Allocator>'
11 |   std::cout << S{} << '\n';
   |                  ^

Why can't the compiler use the std::string conversion? Is there a difference between the conversion function of the built-in and class type?

like image 667
康桓瑋 Avatar asked Nov 09 '25 01:11

康桓瑋


1 Answers

Because operator<< for std::basic_string is a template taking 3 template parameters:

template <class CharT, class Traits, class Allocator>
std::basic_ostream<CharT, Traits>&
    operator<<(std::basic_ostream<CharT, Traits>& os,
               const std::basic_string<CharT, Traits, Allocator>& str);

And implicit conversion won't be considered in template argument deduction:

Type deduction does not consider implicit conversions (other than type adjustments listed above): that's the job for overload resolution, which happens later.

Then given std::cout << S{};, the template parameter CharT, Traits and Allocator can't be deduced on the 2nd function argument.

On the other hand, operator<< for const char* doesn't have such issue; given std::cout << S{};, the template parameter CharT and Traits would be deduced only from the 1st function argument. After deduction, the implicit conversion from S to const char* will be performed and the calling works well.

like image 182
songyuanyao Avatar answered Nov 10 '25 17:11

songyuanyao



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!