Class 对象到字符串的隐式转换运算符

Implicit Conversion Operator for Class Objects to Strings

我正在了解有关隐式转换运算符的更多信息,并且我注意到隐式用户定义的字符串转换有些奇怪。下面是代码。

#include <iostream>
#include <string>

using std::cout;
using std::endl;
using std::string;

class A {
    public:
        A() {
            *value = "YIKERS";
        } 
        operator string&() {
            return *this->value;
        }
        string* value;
};


int main() {
    A abc;
    cout << abc << endl; 
// compile error: invalid operands to binary expression ('std::__1::ostream' (aka
// 'basic_ostream<char>') and 'A')
    return 0;
}

关于我为什么会收到此编译错误的任何想法?我在想这可能意味着对象没有被隐式转换为字符串?如果是这样,为什么不呢?有没有办法来解决这个问题?转换运算符适用于其他数据类型,如 int、float、char 等。

首先,我认为您没有按预期使用 std::string value。这会导致另一个编译错误(至少在 gcc 10.2 上)。 看起来你想要一个字符串并且你正在使用一个指向字符串的指针。 这可以通过将 string* value 替换为 string value、将 operator string&() 替换为 operator string() 以及将 *value = "YIKERS' 替换为 value = "YIKERS" 来解决。对于最后一个,您可能还想检查初始化列表。

关于当前编译错误:

编译错误是由代码 cout << abc 试图在类型 A 的 object 上使用运算符 << 引起的。但是,您没有重载此运算符。 在您的示例中,这可能类似于

friend std::ostream &operator<<(std::ostream &output, const A &a ) 
{ 
    output << a.value;
    return output;            
}

即使您将 user-defined 转换为 std::string,您仍然会遇到编译时错误。 link 解释的比我想象的要好 Why cannot use cout with user-defined conversion to std::string?

上面link的解释我是这样理解的:

string header 为 operator<<std::basic_ostream 定义了以下重载:

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

此外,std::string 实际上是 std::basic_string<char> 的类型定义。

但是,如果转换是隐式的,则以下规则生效:

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

因此,编译器无法从 A 推导出函数的第二个参数(例如 const std::basic_string<CharT, Traits, Allocator>& str)。但是,它可以为 string 推导出它,因此您可以像 static_cast<string>(abc) 一样将 abc 显式转换为 string,这样就可以了。