![](/img/trans.png)
[英]Static vs. Member Operator Overloads: std::operator<< and std::ostream::operator<<
[英]Ambiguity Errors with operator<< Overloads in custom std::ostream Subclass
在尝试开发一个继承自std::stringbuf
stringbuf 和std::ostream
的 class 并为其提供自定义operator<<()
重载(这应该适用于这个 class,但不适用于一般的std::ostream
)时,我得到了一些我不明白的歧义错误。
问题在以下代码的下半部分。 如果我删除operator<<()
重载,我不会收到任何错误( g++ --std=c++17 -o foo.exe foo.cpp
using g++ 9.2.0, MSYS2 build on Windows)。
#include <iostream>
#include <ostream>
#include <sstream>
class MyStream:
private std::stringbuf,
public std::ostream
{
public:
MyStream() noexcept:
std::stringbuf(),
std::ostream(this)
{}
~MyStream()
{
if (pptr() - pbase() < 2)
{ sync(); }
}
protected:
virtual int sync() override
{
// make sure there actually is something to sync
if (pptr() - pbase() < 2)
{ return 0; }
const std::string message{str()};
const std::size_t length{message.length()};
// update the pointers for the next sync
setp(pbase() + length, epptr());
std::cout << message;
return std::stringbuf::sync();
}
};
MyStream& operator<<(MyStream& out, bool boolean) noexcept
{ return out << (boolean ? "yes" : "no"); }
/* ↑
more than one operator "<<" matches these operands:
-- function template "std::basic_ostream<_Elem, _Traits>
&std::operator<<(std::basic_ostream<_Elem, _Traits> &_Ostr, const char *_Val)"
-- function template "std::basic_ostream<char, _Traits>
&std::operator<<(std::basic_ostream<char, _Traits> &_Ostr, const char *_Val)"
-- function template "std::basic_ostream<_Elem, _Traits>
&std::operator<<(std::basic_ostream<_Elem, _Traits> &_Ostr, const _Elem *_Val)"
-- function "operator<<(MyStream &out, bool boolean) noexcept"
-- operand types are: MyStream << const char *
*/
int main()
{
MyStream stream;
stream << "Hello World" << std::endl;
/* ↑
more than one operator "<<" matches these operands:
-- function template "std::basic_ostream<_Elem, _Traits>
&std::operator<<(std::basic_ostream<_Elem, _Traits> &_Ostr, const char *_Val)"
-- function template "std::basic_ostream<char, _Traits>
&std::operator<<(std::basic_ostream<char, _Traits> &_Ostr, const char *_Val)"
-- function template "std::basic_ostream<_Elem, _Traits>
&std::operator<<(std::basic_ostream<_Elem, _Traits> &_Ostr, const _Elem *_Val)"
-- function "operator<<(MyStream &out, bool boolean) noexcept"
-- operand types are: MyStream << const char [12]
*/
}
为什么我的bool
重载是char*
参数的有效候选者? 我怎样才能正确地做到这一点?
在linux (g++ (Ubuntu 7.4.0-1ubuntu1~18.04.1) 7.4.0) 下这似乎对我有用:
MyStream& operator<<(MyStream& out, bool boolean)
{
out << (boolean ? "yes" : "no");
return out;
}
我只更改了回拨电话。 这是因为out << (boolean? "yes": "no")
将对char*
类型使用基本ostream operator<<
,因此返回std::basic_ostream<char>
类型而不是MyStream
返回值类型。
然后在main()
中使用带有MyStream operator<<
的bool
类型:
int main()
{
MyStream stream;
bool b=true;
stream << b << "Hello World" << b << std::endl;
//by contrast, this should output "yesHello Worldyes"
//stream << b << "Hello World";
//stream << b << std::endl;
//and so would this kind of ugliness! lol
//static_cast<MyStream&>(stream << b << "Hello World") << b << std::endl;
}
..但是一旦为语句的"Hello World"
部分调用基类ostream operator<<
,它当然会返回std::basic_ostream<char>
类型:)
..然后在那之后,因为bool
类型没有现有的ostream operator<<
, bool b
类型将被隐式提升为int
,因此 output 是:
yesHello World1
!
但是您似乎遇到了其他错误。 因此,虽然我手头没有 MSYS2,但我确实尝试使用 Visual Studio 在 WinOS 上编译代码。 就我而言,至少,由于 VS STL 实现引起的歧义,您的main()
立即失败:
int main()
{
MyStream stream;
stream << "Hello World" << std::endl;
}
无需对您当前的方法产生怀疑,因为评论中已经发生了这种情况。 但只是为了回答您的问题; 那么一种方法是为处理char*
类型的MyStream
实现另一个operator<<
:
#include <iostream>
#include <ostream>
#include <sstream>
class MyStream:
private std::stringbuf,
public std::ostream
{
public:
MyStream() noexcept:
std::stringbuf(),
std::ostream(this)
{}
~MyStream()
{
if (pptr() - pbase() < 2)
{ sync(); }
}
protected:
virtual int sync() override
{
// make sure there actually is something to sync
if (pptr() - pbase() < 2)
{ return 0; }
const std::string message{str()};
const std::size_t length{message.length()};
// update the pointers for the next sync
setp(pbase() + length, epptr());
std::cout << message;
return std::stringbuf::sync();
}
};
MyStream& operator<<(MyStream& out, const char* str)
{
static_cast<std::ostream&>(out) << str;
return out;
}
MyStream& operator<<(MyStream& out, bool boolean) noexcept
{ return out << (boolean ? "yes" : "no"); }
int main()
{
MyStream stream;
bool b=1;
stream << b << " oook " << b << std::endl;
}
或者,由于MyStream
实际上是从ostream
派生的,因此我们可以使用任何operator<<
来表示具有显式强制转换的ostream
类型。 例如:
#include <iostream>
#include <ostream>
#include <sstream>
class MyStream:
private std::stringbuf,
public std::ostream
{
public:
MyStream() noexcept:
std::stringbuf(),
std::ostream(this)
{}
~MyStream()
{
if (pptr() - pbase() < 2)
{ sync(); }
}
protected:
virtual int sync() override
{
// make sure there actually is something to sync
if (pptr() - pbase() < 2)
{ return 0; }
const std::string message{str()};
const std::size_t length{message.length()};
// update the pointers for the next sync
setp(pbase() + length, epptr());
std::cout << message;
return std::stringbuf::sync();
}
};
std::ostream& operator<<(MyStream& out, bool boolean) noexcept
{
return static_cast<std::ostream&>(out) << (boolean ? "yes" : "no");
}
int main()
{
MyStream stream;
bool b=1;
stream << b << " ooOok ";
stream << b << std::endl;
}
output 希望是:
yes ooOok yes
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.