作为可选 (!) 函数参数的 std::ostream

3

我希望声明一个函数,默认情况下将内容写入std::out,如果提供了其他输出流,则可以选择启用将内容写入其他输出流。例如:

print_function(std::string & str, 
               std::ostream & out = std::cout, 
               std::ostream & other = nullptr) // <-- how to make it optional???
{
    out << str;
    if (other == something) // if optional 'other' argument is provided
    {
        other << str;
    }
}

设置nullprt显然不起作用,但是如何做到这一点呢?


相关:https://dev59.com/c2gt5IYBdhLWcg3wxARj - lorro
2
在我看来,使用两个重载函数会更加自然,一个带有两个参数,另一个带有三个参数。 - user1084944
1
@Hurkyl:或者保留带有2个参数的那个,并传递一个“tee_stream”。 - Jarod42
在这里,使用一个吞噬输入的流(就像https://dev59.com/c2gt5IYBdhLWcg3wxARj中接受的答案)是一个糟糕的解决方案。 - user2249683
3个回答

7

使用指针或者boost::optional

void print_function(std::string & str, 
               std::ostream & out = std::cout, 
               std::ostream* other = nullptr)
{
    out << str;
    if (other)
    {
        *other << str;
    }
}

或者

void print_function(std::string & str, 
               std::ostream & out = std::cout, 
               boost::optional<std::ostream&> other = boost::none)
{
    out << str;
    if (other)
    {
        *other << str;
    }
}

1
我会保留使用 boost::optional 方法......或者至少在指针方法之前。 - Nawaz
1
@Nawaz:有些人不想要boost依赖 :-( 。所以在optional出现在``std::`之前,我们就只能这样了。 - Jarod42
据我上次检查,可选引用已经从std中排除。 - Yakk - Adam Nevraumont
或者使用C++17中的std::optional :) - vladon

1
你可以使用boost::optional或指针,如{{link1:@Jarod42建议}}。然而,这两种方法都需要在函数体中使用条件语句。
以下是另一种方法,其优点在于函数体的简单性:
 void print_function(std::string & str, 
              std::ostream & out = std::cout, 
              std::ostream& other = null_stream)
{
     out << str;
     other << str;  //no "if" required here.
 }

以下是如何定义null_stream对象的方法:

#include <boost/iostreams/stream.hpp>
#include <boost/iostreams/device/null.hpp>

boost::iostreams::stream<boost::iostreams::null_sink> null_stream {
          boost::iostreams::null_sink{} 
};

这里的null_stream是一个什么都不做的std::ostream。还有其他实现方式

希望对你有所帮助。


1

我会简单地使用函数重载,而不是默认参数。

// declare the functions in a header

void print_function(std::string &str);
void print_function(std::string &str, std::ostream &ostr);
void print_function(std::string &str, std::ostream &ostr, std::ostream &other);

// and in some compilation unit, define them

#include "the_header"

void print_function(std::string &str)
{
       print_function(str, std::cout);
}

void print_function(std::string &str, std::ostream &ostr)
{
     // whatever
}

void print_function(std::string & str, 
                    std::ostream &ostr, 
                    std::ostream &other)
{
    print_function(str, ostr);

    other << str;
}

这三个函数的版本都可以实现你想要的功能。根据你的需求,任何一个版本都可以使用其他版本来实现。

如果你需要在这三个函数中交错逻辑(例如,影响other的语句需要与另外一个函数的语句交错),那么可以引入辅助函数,将逻辑分成更细粒度的部分来实现。


这可能是最简单和直接的解决方案,也不需要使用boost。 - Stingery

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接