隐式转换运算符不参与运算符重载
Implicit conversion operator doesn't kick in with operator overloading
考虑以下示例:
#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
}
注释行导致编译错误:no match for 'operator+'
。为什么?我最初的想法是,它会先使用 operator std::string
进行转换,然后执行对 operator+
的调用,就像对 .append
所做的那样。
它只是一级隐式转换,所以应该执行并且应该考虑到,不是吗?
显式转换为 std::string 对我有用:https://godbolt.org/g/WZG78z
std::string s2 = "Line: "s + std::string(loc) + "\n"; // was error
您的运算符是模板化的,因此需要推导模板参数。你不能那样做,因为编译器试图将 basic_string<_CharT, _Traits, _Alloc>
与你的 Location
匹配,但失败了。
所以问题是重载,而不是转换,因为代码实际上从未达到那个点。
改变这个:
std::string s2 = "Line: "s + loc + "\n"s;
对此:
std::string s2 = "Line: "s + std::string(loc) + "\n"s;
你应该没问题,因为如果你仔细查看编译器错误,它会提到:
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
^~~
和其他类似的消息。
考虑以下示例:
#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
}
注释行导致编译错误:no match for 'operator+'
。为什么?我最初的想法是,它会先使用 operator std::string
进行转换,然后执行对 operator+
的调用,就像对 .append
所做的那样。
它只是一级隐式转换,所以应该执行并且应该考虑到,不是吗?
显式转换为 std::string 对我有用:https://godbolt.org/g/WZG78z
std::string s2 = "Line: "s + std::string(loc) + "\n"; // was error
您的运算符是模板化的,因此需要推导模板参数。你不能那样做,因为编译器试图将 basic_string<_CharT, _Traits, _Alloc>
与你的 Location
匹配,但失败了。
所以问题是重载,而不是转换,因为代码实际上从未达到那个点。
改变这个:
std::string s2 = "Line: "s + loc + "\n"s;
对此:
std::string s2 = "Line: "s + std::string(loc) + "\n"s;
你应该没问题,因为如果你仔细查看编译器错误,它会提到:
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
^~~
和其他类似的消息。