隐式类型转换无效

时间:2013-08-09 18:53:54

标签: c++

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已经是从stringchar *的隐式转换,如果我使用强制转换为字符串,它将不会执行{{1}的两级转换}。直接转换为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的一些特殊内容。假设部分正确且部分错误。

2 个答案:

答案 0 :(得分:4)

explicit关键字意味着您必须自己明确地执行转换,例如std::string(Test{})。它会禁用隐式转换。

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

规则是,在模板参数推导期间,不会尝试用户定义的转换。但是,正如您所指出的,如果您只有一个转换运算符,那么它就会编译。那是因为重载不是函数模板。看看reference page,你会看到:

basic_ostream& operator<<( int value );

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

答案 1 :(得分:2)

operator<<(或std::string)的std::basic_string重载是一个功能模板。在模板参数推导期间不考虑用户定义的转换,因此编译器不认为string重载是匹配的。

要避免错误,请为您的班级定义重载basic_ostream& operator<<(basic_ostream&, Test&)