【问题标题】:ostream and operator std::basic_string<char, std::char_traits<char>, std::allocator<char>>?ostream 和运算符 std::basic_string<char、std::char_traits<char>、std::allocator<char>>?
【发布时间】:2017-11-09 11:36:33
【问题描述】:

the answer,我了解到std::string只是std::basic_string&lt;char, std::char_traits&lt;char&gt;, std::allocator&lt;char&gt;&gt;的typedef,模板参数替换不考虑用户定义的转换,所以编译器无法从类型中推断出CharT、Traits或Allocator类型矩形,所以这个重载不参与重载决议。

现在我用 std::basic_string, std::allocator> 代替 std::string:

class Rectangle
{
public:
    Rectangle(double x, double y) : _x(x), _y(y) {}
    operator std::basic_string<char, std::char_traits<char>, std::allocator<char>> () {
        return std::basic_string<char, std::char_traits<char>, std::allocator<char>>(to_string(_x) + " " + to_string(_y));
    }
    //operator double() {
    //  return _x;
    //}
private:
    double _x, _y;
    double getArea() { return _x * _y; }
};

int main()
{
    Rectangle r(3, 2.5);
    cout << r << endl;
    return 0;
}

它仍然失败。为什么?

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

【问题讨论】:

  • 你可以定义std::ostream&amp; operator&lt;&lt; (std::ostream&amp; stream, const Rectangle&amp; rectangle)或者使用cout &lt;&lt; (string)r

标签: c++


【解决方案1】:

现在我用 std::basic_string, std::allocator> 替换 std::string:
它仍然失败。为什么?

您误解了最初的问题。这不是因为您使用了std::string 而不是直接的std::basic_string&lt;char, std::char_traits&lt;char&gt;, std::allocator&lt;char&gt;&gt;。 typedef 只是现有类型的另一个名称。您的两个转换运算符完全相同。您可以通过尝试将它们都放在类定义中来验证是否会导致重新定义错误。

在解决 operator&lt;&lt; 的重载时,两者都不会被考虑在内,因为转换不会应用于模板函数排序。

【讨论】:

  • 标准中有对应的文字吗?我试图通过重载解析和模板进行解析,但找不到。
  • @Incomputable - 它是 [temp.over]/1[temp.deduct] 中的某些内容的组合,我目前很难确定。
  • @Incomputable - Aha, it's paragraph 4.
  • 虽然它仍然完全不明显:)
  • @Incomputable - 如果它是显而易见的,那不会是我们所知道和喜爱的 C++,不是吗? :)
【解决方案2】:

Overload resolutionfirst 找到一组可能调用的函数。在这个阶段进行模板推导,看一个模板是否是可能的候选者。

然后,如果找到多个函数,则在尝试在候选中找到最接近的匹配时会考虑转换函数。

在您的情况下,永远不会考虑采用std::string 的运算符,因为编译器无法从Rectangle 推断出CharTetc。


一种解决方案是跳过转换运算符,而是为Rectangle 添加一个operator&lt;&lt;。在里面你可以打电话给os &lt;&lt; to_string(...等等。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-28
    相关资源
    最近更新 更多