给定代码:
#include <iostream>
// this is my custom streamer which functions like ostream:
// MyStream() << 123 << "456" << 2.0 << ...;
class MyStream {
public:
template <typename T>
// It only supports streaming basic types,such as int/float/char/char* ...
MyStream& operator<<(T&& t) {
// std::cout is just an example, actually I stream `t` to a buffer
std::cout << t << std::endl;
return *this;
}
};
struct Test {
int x;
float y;
};
// I want to stream struct Test:
// MyStream() << Test();
// It will be more useful if I can stream `Test` to iostream or stringstream.
// std::cout << Test();
// std::stringstream ss;
// ss << Test();
// So I implemented a template operator overload function
template <typename Stream>
Stream& operator<<(Stream& s, const Test& t) {
return s << t.x << ", " << t.y;
}
int main() {
const Test t = {1, 2.0};
MyStream ms;
// but this doesn't work as expected
ms << t;
Test t2 = {3, 4.0};
ms << t2;
}
字符串
它生成编译错误:
source>:26:8: error: use of overloaded operator '<<' is ambiguous (with operand types 'MyStream' and 'const Test')
ms << t;
~~ ^ ~
<source>:7:15: note: candidate function [with T = const Test &]
MyStream& operator<<(T&& t) {
^
<source>:19:9: note: candidate function [with Stream = MyStream]
Stream& operator<<(Stream& s, const Test& t) {
^
1 error generated.
型
代码链接:https://godbolt.org/z/Gf51fjTMx
实际上,LogStream
是第三方库fmt
的 Package 器,我想让它像iostream
一样工作。但它不支持自定义结构类型。因此,我添加了另一个重载函数模板Stream& operator<<(Stream& s, const Test& t)
,以允许自定义结构的流。
问:
如果我不改变调用位置代码(main
函数),如何使这两个函数重载中的任何一个更加专用化?
2条答案
按热度按时间sr4lhrrt1#
字符串
最好不要写像
MyStream
这样的类,它们往往很脆弱。如果你需要一个专门的流,可以从std::basic_{i,o}stream
派生你自己的流和/或编写你自己的streambuf
实现。更好的是,抛弃ostream格式,支持
std::format
。jjjwad0x2#
//它只支持流的基本类型,例如int/float/char/char*...
它没有反映在签名中。您可以为此添加约束:
字符串
然后,该重载不再是
/* const */ Test /* & */
的可行候选。Demo