尝试开发一个同时继承std::stringbuf
和std::ostream
的类并为其提供自定义的operator<<()
重载时(该重载应该适用于此类,但不适用于std::ostream
通常),我遇到了一些我不理解的歧义错误。
问题在以下代码的下半部分。如果我消除了operator<<()
重载,则不会出现任何错误(使用g ++ 9.2.0,Windows上的MSYS2构建的g++ --std=c++17 -o foo.exe foo.cpp
)。
#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*
参数的有效候选者?如何正确执行此操作?
答案 0 :(得分:1)
This在 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")
将对ostream operator<<
类型使用基数char*
并因此返回std::basic_ostream<char>
类型而不是返回值MyStream
。
然后在main()
中将bool
类型与MyStream operator<<
一起使用会起作用:
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;
}
..但是一旦对语句的ostream operator<<
部分调用了基类"Hello World"
,它当然会返回std::basic_ostream<char>
类型:)
..然后,由于ostream operator<<
类型不存在bool
,因此bool b
类型将隐式提升为int
,因此输出为:
yesHello World1
!
但是您似乎遇到了其他错误。因此,尽管我没有MSYS2,但是我确实尝试使用Visual Studio在WinOS上编译代码。就我而言,至少由于VS STL实现引起的歧义,您的main()
立即失败了:
int main()
{
MyStream stream;
stream << "Hello World" << std::endl;
}
无需对您当前的方法表示怀疑,因为评论中已经发生了这种情况。但是只是为了回答您的问题;那么一种方法是为operator<<
实现另一个MyStream
类型的char*
来处理#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;
}
用于yes ooOok yes
类型。例如:
model<-Prod.Rate~ lag(Prod.Rate)+Mkt.Rate+Censor
fd<-plm(model, data=FD, model="fd)
希望输出在哪里:
$itemnumber