【问题标题】:Implicit conversion operator doesn't kick in with operator overloading隐式转换运算符不会与运算符重载一起使用
【发布时间】:2017-10-20 05:47:27
【问题描述】:

考虑以下示例:

#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 所做的那样。

这只是隐式转换的一级,所以应该执行并且应该考虑到,不是吗?

Live Demo

【问题讨论】:

  • 抱歉问,但我看不到工作代码。 s 是什么?
  • 好的@Holt,谢谢!
  • 这里的问题是当你做.append的时候,模板参数已经在"Line"s的构造过程中被实例化了,所以没有发生模板参数推导(.append想要std::string ),但是 + 运算符是模板化的,所以你需要推导出 CharTTraitsAllocator,你不能因为编译器无法匹配 basic_string&lt;...&gt;Location - 你甚至没有达到转换阶段,失败的是过载阶段。
  • @Holt 谢谢。我正在寻找技术解释。如果您作为完整答案发布,我会接受。

标签: c++ c++11 operator-overloading conversion-operator


【解决方案1】:

您的运算符是模板化的,因此需要推导模板参数。您不能这样做,因为编译器会尝试将 basic_string&lt;_CharT, _Traits, _Alloc&gt; 与您的 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
                                ^~~

和其他类似的消息。

【讨论】:

    【解决方案2】:

    显式转换为 std::string 对我有用:https://godbolt.org/g/WZG78z

        std::string s2 = "Line: "s + std::string(loc) + "\n"; // was error
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-12-09
      • 1970-01-01
      • 1970-01-01
      • 2014-08-18
      • 1970-01-01
      • 2013-08-25
      • 1970-01-01
      相关资源
      最近更新 更多