【问题标题】:Why can't the compiler use the std::string conversion function of the class when perform operator<<?为什么编译器在执行operator<<时不能使用类的std::string转换函数?
【发布时间】:2021-01-26 08:23:01
【问题描述】:

考虑下面的struct,它有一个用户定义的转换函数,可以将自己转换为const char*

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

&lt;iostream&gt;一起工作,我们可以打印struct S而没有错误消息:

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

但是如果我将返回类型更改为std::string:

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

我收到此编译器错误消息:

<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';
   |                  ^

为什么编译器不能使用std::string 转换?内置和类类型的转换函数有区别吗?

【问题讨论】:

    标签: c++ iostream cout stdstring


    【解决方案1】:

    因为operator&lt;&lt; for std::basic_string是一个带有3个模板参数的模板:

    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);
    

    并且template argument deduction中不会考虑隐式转换:

    类型推导不考虑隐式转换(除了上面列出的类型调整):这是重载解析的工作,稍后会发生。

    那么给定std::cout &lt;&lt; S{};,模板参数CharTTraitsAllocator不能在第二个函数参数上推导出来。

    另一方面,operator&lt;&lt; for const char* 没有这样的问题;给定std::cout &lt;&lt; S{};,模板参数CharTTraits 将仅从第一个函数参数推导出来。推演后会进行Sconst char*的隐式转换,调用正常。

    【讨论】:

      猜你喜欢
      • 2011-10-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-05-30
      • 2018-11-14
      • 2019-07-04
      • 2012-10-19
      相关资源
      最近更新 更多