如何std::cout<<具有许多(模棱两可的)用户定义转换函数的类型?

How to std::cout << a type which has many (ambiguous) user-defined conversion functions?

提问人:RandomGuy 提问时间:10/14/2023 最后编辑:Jan SchultkeRandomGuy 更新时间:10/14/2023 访问量:111

问:

在这里,我有一个类,它处理的大数远远超出了.它将其数据存储为 .现在我这里有很多很多转换器:c++long longstd::string

class BigInt {
private:
    std::string x;
public:
    operator std::string()        { return x;              }
    operator int()                { return std::stoi(x);   }
    operator long long()          { return std::stoll(x);  }
    operator unsigned long long() { return std::stoull(x); }
    operator double()             { return std::stod(x);   }
    operator long double()        { return std::stold(x);  }
    ...
    BigInt(std::string a) : x(a) {}
    BigInt(long long a) : x(to_string(a)) {}
    ...
}
int main() {
    BigInt x = 10485761048576;
    std::cout << x << std::endl; // Error!
}

但是发生的情况是我收到一个错误:

多个运算符与这些操作数匹配。

这基本上意味着该函数不知道选择哪个转换器。那么,在访问函数时,是否有一种“默认”转换器选择其中一个转换器作为默认转换器呢?std::cout

如果没有那种东西,那么我想每次我想将参数传递到某种重载函数时,我都必须调用类似的东西。std::cout << (std::string)x << std::endl;

C++ Operator-Overloading 隐式转换 重载解决

评论

0赞 bolov 10/14/2023
为什么不让流运算符重载呢?
0赞 user12002570 10/14/2023
Dupe 重载类的流插入 (<<) 运算符。这在任何初学者 c++ 书籍中都有解释。
1赞 HolyBlackCat 10/14/2023
如果有其他可行的解决方案,请重新打开它。
0赞 Swift - Friday Pie 10/14/2023
对整数值的隐式转换违背了类的目的。你必须制造它们explicit
0赞 n. m. could be an AI 10/14/2023
通用的“数字”类型是一个相当糟糕的主意。你想要整数还是实数?它们是根本不同的。

答:

1赞 wohlstad 10/14/2023 #1

您可以为 以下 提供 std::ostream 运算符的重载<<BigInt

std::ostream& operator<<(std::ostream& os, const BigInt& obj)
{
    os << static_cast<std::string>(obj);
    return os;
}

为了能够对对象使用转换运算符(如上所述,无论如何这是一个很好的做法),您还需要将它们标记为 const,例如:constoperator<<

//  -----------------------vvvvv--------------
    operator std::string() const { return x; }

现在您可以使用:

int main() 
{
    BigInt x = 10485761048576;
    std::cout << x << std::endl;
}

输出:

10485761048576

现场演示 - Godbolt

评论

0赞 RandomGuy 10/14/2023
等等,它真的不起作用......在我的编译器(MSVC)中,它告诉我,在链接过程中:运算符<<已经在BigNumbers.cpp中定义,找到了一个或多个乘法定义的符号。我认为这是因为我已经创建了从 BigInt 到 int 和 long long 的转换器等等?
1赞 wohlstad 10/14/2023
如果在头文件中定义,则将其设为 () 或仅在头 () 中放置声明,并将实现放在 cpp 文件中。operator<<inlineinline std::ostream& operator<< ...std::ostream& operator<<(std::ostream& os, const BigInt& obj);
0赞 RandomGuy 10/14/2023
谢谢,这确实解决了问题:将其标记为内联。这实际上是最简单的方法之一,不是吗
0赞 Swift - Friday Pie 10/14/2023
这仅仅是因为您的转换器是隐式的......他们优先于非成员运营商
0赞 Jan Schultke 10/14/2023
您可以将 简化为一行: .operator<<return os << static_cast<std::string>(obj)