运算符的歧义错误<<自定义 std::ostream 子类中的重载



在尝试开发一个继承std::stringbufstd::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]
*/
}

为什么我的重载boolchar*参数的有效候选者?我怎样才能正确地做到这一点?

这似乎在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

相关内容

  • 没有找到相关文章

最新更新