为什么在执行operator <<时编译器为什么不能使用类的std :: string转换函数?

问题描述

请考虑以下struct与用户定义的转换功能,该功能可以将自身转换为const char*;

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

<iostream>一起使用,我们可以打印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转换?内置类型和类类型的转换函数之间有区别吗?

解决方法

因为operator<< 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 << S{};,模板参数CharTTraitsAllocator不能在第二个函数参数上推导。

另一方面,operator<< for const char*没有这样的问题;给定std::cout << S{};,模板参数CharTTraits仅从第一个函数参数推导出。扣除后,将执行从Sconst char*的隐式转换,并且调用效果很好。

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...