在尝试开发一个继承std::stringbuf
和std::ostream
的类并为其提供自定义operator<<()
重载(这应该适用于这个类,但不适用于一般的std::ostream
(,我得到了一些我不明白的歧义错误。
问题出在以下代码的下半部分。如果我删除operator<<()
重载,我不会收到任何错误(g++ --std=c++17 -o foo.exe foo.cpp
在 Windows 上使用 g++ 9.2.0、MSYS2 构建(。
#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
,因此输出为: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
派生的,因此我们可以对具有显式强制转换的ostream
类型使用任何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();
}
};
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;
}
其中输出希望为:
yes ooOok yes