1
class Test {
public:
    operator string() {
        return string{"TEST!"};
    }
};

int main() {
    cout << Test{};
}

我期待 Test 对象将被隐式转换为字符串并输出,但它给了我错误:

error: cannot bind 'std::ostream {aka std::basic_ostream<char>}' lvalue to 'std::basic_ostream<char>&&'

这种显式转换有效:

cout << string{Test{}};

我通过转换为const char*

class Test {
public:
    operator const char*() {
        return "TEST!";
    }
};

然后输出:

cout << Test{}; //Yay it works.

我假设cout << string已经是从stringto的隐式转换char *,如果我使用强制转换为字符串,它将不会从Test to string to char *. 直接转换为 后const char*,它可以工作。(假设有误请指正)


证明假设是正确的

class Test {
public:
    operator string() {
        return string{"TEST!"};
    }
};

ostream& operator<< (ostream& os, string s){
    os << s;
    return os;
}

这将从Test to string和输出字符串执行直接类型推导。在我尝试之后,它起作用了!

cout << Test{}; //YAY WORKS! OUTPUT "TEST!"

有一些特别之处cout << string由 解释Borgleader。假设部分正确,部分错误。

4

2 回答 2

4

explicit关键字意味着您必须std::string(Test{})像. 它禁用隐式转换。

cout << string{Test{}}; // <-- this is explicit, you've got implicit and explicit confused

规则是,在模板参数推导期间,不会尝试用户定义的转换。但是,正如您所注意到的,如果您只有一个转换运算符来 int 编译它。那是因为该重载不是函数模板。看看参考页,你会看到:

basic_ostream& operator<<( int value );

这是一个非模板化的重载,因此编译器将寻找用户定义的转换。

于 2013-08-09T18:55:41.997 回答
2

采用(or )的operator<<重载是函数模板。在模板参数推导期间不考虑用户定义的转换,因此编译器不认为重载是匹配的。std::stringstd::basic_stringstring

为避免该错误,basic_ostream& operator<<(basic_ostream&, Test&)请为您的类定义一个重载。

于 2013-08-09T19:05:36.387 回答