[英]Ambiguity Errors with operator<< Overloads in custom std::ostream Subclass
While trying to develop a class inheriting from both std::stringbuf
and std::ostream
and giving it a custom operator<<()
overload (which should work for this class, but not for std::ostream
in general), I got some ambiguity errors I don't understand.在尝试开发一个继承自
std::stringbuf
stringbuf 和std::ostream
的 class 并为其提供自定义operator<<()
重载(这应该适用于这个 class,但不适用于一般的std::ostream
)时,我得到了一些我不明白的歧义错误。
The problems are in the bottom half of the following code.问题在以下代码的下半部分。 If I remove the
operator<<()
overload, I do not get any errors ( g++ --std=c++17 -o foo.exe foo.cpp
using g++ 9.2.0, MSYS2 build on Windows).如果我删除
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]
*/
}
Why is my overload for bool
a valid candidate for a char*
argument?为什么我的
bool
重载是char*
参数的有效候选者? How can I do this properly?我怎样才能正确地做到这一点?
This seems to work for me under linux (g++ (Ubuntu 7.4.0-1ubuntu1~18.04.1) 7.4.0):在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;
}
I only changed the return call.我只更改了回拨电话。 That's because
out << (boolean? "yes": "no")
will use the base ostream operator<<
for char*
types and hence returns a std::basic_ostream<char>
type rather than a MyStream
return value type.这是因为
out << (boolean? "yes": "no")
将对char*
类型使用基本ostream operator<<
,因此返回std::basic_ostream<char>
类型而不是MyStream
返回值类型。
And then in main()
using a bool
type with a MyStream operator<<
works:然后在
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;
}
..but once the base-class ostream operator<<
is invoked for the "Hello World"
part of the statement, it of course returns a std::basic_ostream<char>
type:) ..但是一旦为语句的
"Hello World"
部分调用基类ostream operator<<
,它当然会返回std::basic_ostream<char>
类型:)
..then after that, because there is no existing ostream operator<<
for bool
types, the bool b
type will get implicitly promoted to a int
and so the output is: ..然后在那之后,因为
bool
类型没有现有的ostream operator<<
, bool b
类型将被隐式提升为int
,因此 output 是:
yesHello World1
! yesHello World1
!
But you seemed to be getting other errors.但是您似乎遇到了其他错误。 So while i do not have MSYS2 to hand, i did try to compile the codes on a WinOS with Visual Studio.
因此,虽然我手头没有 MSYS2,但我确实尝试使用 Visual Studio 在 WinOS 上编译代码。 In my case, at least, your
main()
fails immediately due to ambiguities raised by the VS STL implementation:就我而言,至少,由于 VS STL 实现引起的歧义,您的
main()
立即失败:
int main()
{
MyStream stream;
stream << "Hello World" << std::endl;
}
No need to cast doubt on your current approach as that has already happened in comments.无需对您当前的方法产生怀疑,因为评论中已经发生了这种情况。 but just in an attempt to answer your questions;
但只是为了回答您的问题; then one way round would be to implement another
operator<<
for MyStream
that handles char*
types:那么一种方法是为处理
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;
}
Alternatively, since MyStream
actually is derived from ostream
then we can make use of any operator<<
for the ostream
type with an explicit cast.或者,由于
MyStream
实际上是从ostream
派生的,因此我们可以使用任何operator<<
来表示具有显式强制转换的ostream
类型。 For example:例如:
#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;
}
where the output is hopefully: output 希望是:
yes ooOok yes
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.