与c ++无关的平台/ dev/null

cal*_*pto 21 c++ stream ostream default-parameters

可能重复:
实现no-op std :: ostream

在c ++中是否有任何与NULL等效的流?我想编写一个函数,如果用户希望将内部输出到某个地方,则会接收流,但如果没有,则输出进入某个假的地方

void data(std::stream & stream = fake_stream){
    stream << "DATA" ;
}
Run Code Online (Sandbox Code Playgroud)

我希望能够选择做data()data(std::cout)

Xeo*_*Xeo 34

编辑:从@Johannes绍布两者- litb的邮件在这里稍作修改:

template<typename Ch, typename Traits = std::char_traits<Ch> >
struct basic_nullbuf : std::basic_streambuf<Ch, Traits> {
     typedef std::basic_streambuf<Ch, Traits> base_type;
     typedef typename base_type::int_type int_type;
     typedef typename base_type::traits_type traits_type;

     virtual int_type overflow(int_type c) {
         return traits_type::not_eof(c);
     }
};

// convenient typedefs
typedef basic_nullbuf<char> nullbuf;
typedef basic_nullbuf<wchar_t> wnullbuf;

// buffers and streams
// in some .h
extern std::ostream cnull;
extern std::wostream wcnull;

// in a concrete .cpp
nullbuf null_obj;
wnullbuf wnull_obj;
std::ostream cnull(&null_obj);
std::wostream wcnull(&wnull_obj);
Run Code Online (Sandbox Code Playgroud)

使用那些:

void data(std::ostream& stream = cnull){
  // whatever...
}
Run Code Online (Sandbox Code Playgroud)

现在,这看起来很酷,但是以下内容更短并且有效,因为如果向构造函数提供了空指针ostream,它会自动设置badbit并静默忽略任何写入:

// in .h
extern std::ostream cnull;
extern std::wostream wcnull;

// in .cpp
std::ostream cnull(0);
std::wostream wcnull(0);
Run Code Online (Sandbox Code Playgroud)

标准保证这个工作,从开始27.6.2.2 [lib.ostream.cons] p1描述它的构造函数ostream获取指向streambuf:

效果:构造类的对象,basic_ostream通过调用将初始值分配给基类basic_ios<charT,traits>::init(sb).

从相关功能basic_ios,27.4.4.1 [lib.basic.ios.cons] p3:

void init(basic_streambuf<charT,traits>* sb);
后置条件:此函数的后置条件如表89所示:

表89中的重要一行:

rdstate() - 如果sb不是空指针,则为goodbit,否则为badbit.

如果badbit已设置,则会发生以下情况27.6.2.6 [lib.ostream.unformatted]:

每个未格式化的输出函数通过构造类的对象开始执行sentry.如果此对象返回true,则在转换为bool类型的值时,该函数会尝试生成请求的输出.

这意味着,如果sentry是假的,则不是.以下是sentry转换的方式bool,取自27.6.2.3 [lib.ostream::sentry] p3 & p5:

3)如果在完成任何准备之后,os.good()则是true,ok_ == true否则,ok_ == false.

5)operator bool();
效果:返回ok_.

(ok_ostream::sentry类型的成员bool.)


请注意,这些引号仍然存在于C++ 11中,只是在不同的地方.按照这个答案出现的顺序:

  • 27.6.2.2 [lib.ostream.cons] p1 => 27.7.3.2 [ostream.cons] p1
  • 27.4.4.1 [lib.basic.ios.cons] p3 => 27.5.5.2 [basic.ios.cons]
  • 表89 =>表128
  • 27.6.2.6 [lib.ostream.unformatted] => 27.7.3.7 [ostream.unformatted] p1
  • 27.6.2.3 [lib.ostream::sentry] p3 & p5 => 27.7.3.4 [ostream::sentry] p4 & p5