隐式转换运算符不会导致运算符重载

Dei*_*Dei 5 c++ operator-overloading conversion-operator c++11

请考虑以下示例:

#include <string>
#include <sstream>

struct Location {
    unsigned line;

    template<typename CharT, typename Traits>
    operator std::basic_string<CharT, Traits>() const {
        std::basic_ostringstream<CharT, Traits> ss;
        ss << line;
        return ss.str();
    }
};

int main() 
{
    using namespace std::string_literals;

    Location loc{42};

    std::string s1 = "Line: "s.append(loc) + "\n"s; // fine
    //std::string s2 = "Line: "s + loc + "\n"s; // error
}
Run Code Online (Sandbox Code Playgroud)

注释行会导致编译错误:no match for 'operator+'.为什么?我最初的想法是,它首先用于operator std::string转换然后执行调用operator+,就像它所做的那样.append.

它只是隐式转换的一个级别,所以它应该被执行并且应该被考虑在内,不是吗?

Live Demo

gsa*_*ras 2

您的运算符是模板化的,因此需要推导模板参数。您不能这样做,因为编译器尝试匹配basic_string<_CharT, _Traits, _Alloc>您的Location,但它失败了。

所以问题是重载,而不是转换,因为代码实际上永远不会到达那个点。

改变这个:

std::string s2 = "Line: "s + loc + "\n"s;
Run Code Online (Sandbox Code Playgroud)

对此:

std::string s2 = "Line: "s + std::string(loc) + "\n"s;
Run Code Online (Sandbox Code Playgroud)

你应该没问题,因为如果你仔细观察编译器错误,它会提到:

template argument deduction/substitution failed:
prog.cc:22:32: note:   'Location' is not derived from 'const std::__cxx11::basic_string<_CharT, _Traits, _Alloc>'
   std::string s2 = "Line: "s + loc + "\n"s; // error
                                ^~~
Run Code Online (Sandbox Code Playgroud)

以及其他类似的消息。