简体   繁体   English

C ++在操作数中对标准运算符的隐式转换

[英]C++ implicit conversions in operands to standard operators

I am having some trouble understanding the conditions under which C++ will use an implicit conversion. 我在理解C ++使用隐式转换的条件时遇到了一些麻烦。 Suppose I have a class: 假设我有一个班级:

class SomeClass
{
private:
    int val;
public:
    SomeClass(int i) :val{ i } {}
    operator string() { return to_string(val); }
};

Why is it that when using this class with operators I need to cast to string? 为什么在将此类与运算符一起使用时需要转换为字符串? Why doesn't it just perform the conversion implicitly? 为什么不隐式执行转换呢?

code: 码:

int main(void)
{
    SomeClass sc = 4;
    cout << (string)sc << endl; //prints 4, compiles fine
    cout << sc << endl;//does not compile, no operator "<<" matches these operands

    string str1 = sc;//compiles fine, performs cast
    string str2 = "Base String" + sc;//does not compile, no operator "+" matches these operands
}

This question is more academic than practical as just using a cast is more readable anyway. 这个问题更具学术性而非实际性,因为无论如何使用演员表更具可读性。

std::cout doesn't accept a std::string . std::cout不接受std::string
It accepts a templated std::basic_string , the parameters of which are to be deduced. 它接受一个模板化的std::basic_string ,其参数将被推导出来。
See here for further details. 有关详细信息,请参见此处

Let's consider the following example: 让我们考虑以下示例:

#include<string>

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

template <class CharT, class Traits, class Allocator>
void f(const std::basic_string<CharT, Traits, Allocator> &) {}

template <class CharT, class Traits, class Allocator>
void f(std::basic_string<CharT, Traits, Allocator> &) {}

int main(void) {
    SomeClass sc{};
    f((std::string)sc);
    //f(sc);
}

It is similar to what happens in your case. 它类似于你的情况。
Of course, f(sc) doesn't compile for almost the same reason. 当然, f(sc)不会因为几乎相同的原因而编译。

The problem is that to deduce the template parameters SomeClass should be converted to a std::string . 问题是推导出模板参数SomeClass应该转换为std::string To be able to convert it to a std::string , the compiler should guess that a valid overload exists and try to use it. 为了能够将其转换为std::string ,编译器应该猜测存在有效的重载并尝试使用它。 Anyway, such a viable function doesn't exist from its point of view, for template parameters are still to be deduced and to deduce them the compiler should guess that an overload for SomeClass exists after a cast. 无论如何,从它的角度来看,这样一个可行的函数是不存在的,因为仍然需要推导出模板参数并推导它们,编译器应该猜测在转换后SomeClass的重载是存在的。 It can't, because... And so on. 它不能,因为......等等。

I haven't checked it, but I would bet that something similar applies to operator+ too. 我没有检查过,但我敢打赌类似的东西也适用于operator+

The operator<< overload that gets used when you write cout << (string)sc is a function template: 编写cout << (string)sc时使用的operator<< overload是一个函数模板:

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

This is because std::string is itself a class template, and can be instantiated with other types than char , and should still be printable if the characters are written to a stream of that same character type. 这是因为std::string本身是一个类模板,并且可以使用除char之外的其他类型进行实例化,并且如果将字符写入相同字符类型的流,则仍应该是可打印的。 In fact, that's exactly what happens with std::wstring , where CharT is wchar_t rather than char . 实际上,这正是std::wstring所发生的情况,其中CharTwchar_t而不是char That same operator<< works, provided you use a suitable stream. 如果您使用合适的流,那么同一个operator<<可以工作。

When you write cout << sc , that particular overload is considered. 当你编写cout << sc ,会考虑特定的重载。 That overload is then rejected because the compiler cannot deduce which type to use for CharT and the others. 然后拒绝该重载,因为编译器无法推断出哪种类型用于CharT和其他CharT It would only be able to deduce the type if it already knew that the conversion would be performed, but the conversions are not considered just yet, they would only be checked in a slightly later stage. 如果它已经知道转换将被执行,它只能推断出类型,但转换不仅仅被考虑,它们只会在稍后的阶段进行检查。

If there were a non-template operator<< overload that took std::string , then it would work, sc would be converted implicitly. 如果有一个非模板operator<< overload,它带有std::string ,那么它就可以工作, sc会被隐式转换。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM