在std :: ostream输出后添加新行而不显式调用它

时间:2018-03-17 02:43:35

标签: c++ delegates ostream

以下示例最好地说明了我的问题:

$2

我的(工作)尝试实现此功能:

class Stream
{
public:
    Stream(std::ostream& os)
        :
        stream(os)
    {
    }

    auto getStream()
    {
        return std::pair<std::ostream&, std::unique_ptr<StreamDelegate>>(stream, std::make_unique<StreamDelegate>(stream));
    }

private:
    std::ostream& stream;
};  

int main()
{
    Stream os(std::cout);
    os.getStream() << "input1" << "input2"; 
//execute some code without explicitly calling it 
//such os.getStream() << std::endl; 
}

是否还有其他更优雅的方式来实现此功能?

此外,我发现我的代码可能存在陷阱。在下面的代码中说明:

class StreamDelegate
{
public:
    StreamDelegate(std::ostream& os)
        :
        stream(os)
    {
    }
    ~StreamDelegate()
    {
        //some delegated functionality
        //exmpl:
        stream << std::endl;
    }

private:
    std::ostream& stream;
};

class Stream
{
public:
    Stream(std::ostream& os)
        :
        stream(os)
    {
    }

    auto getStream()
    {
        return std::pair<std::ostream&, std::unique_ptr<StreamDelegate>>(stream, std::make_unique<StreamDelegate>(stream));
    }

private:
    std::ostream& stream;
};

int main()
{
    Stream os(std::cout);
    os.getStream().first << "input1" << " input2";
    os.getStream().first << "line2: input1" << " line2: input 2";

    std::cin.get();
}

由于int main() { Stream os(std::cout); auto pitfall = os.getStream(); pitfall.first << "line1"; pitfall.first << "should be line 2"; std::cin.get(); } 的返回值已分配给变量,因此os.getStream()没有破坏,因此没有所需的行为。

我不打算将StreamDelegate分配给变量,但是如果有办法解决这个问题,我想知道。

另外我知道我可以通过以与Stream::getStream()相同的方式实现StreamDelegate析构函数来避免Stream,但我可能希望这可以在单例上工作。< / p>

1 个答案:

答案 0 :(得分:1)

我认为您使用RAII的想法很好。如果您为operator<<实施模板化Stream并让您返回StreamDelegate它会更容易使用,并且通过分配变量来破坏销毁更加困难。

#include <iostream>

class StreamDelegate
{
public:
    StreamDelegate(std::ostream& os) : stream(os) {}

    ~StreamDelegate() {
        //some delegated functionality
        //exmpl:
        stream << std::endl;
    }

    template <typename T>
    StreamDelegate& operator<<(T&& val) {
        stream << std::forward<T>(val);
        return *this;
    }
    StreamDelegate& operator=(const StreamDelegate&) = delete;
    StreamDelegate(const StreamDelegate&) = delete;

private:
    std::ostream& stream;
};

class Stream
{
public:
    Stream(std::ostream& os) : stream(os) {}

    template <typename T>
    StreamDelegate operator<<(T&& val) {
        stream << std::forward<T>(val);
        return StreamDelegate(stream);
    }

private:
    std::ostream& stream;
};

int main()
{
    Stream os(std::cout);
    os << "input1" << " input2";
    os << "line2: input1" << " line2: input 2";

    std::cin.get();
}

修改

我明确地将StreamDelegate的copy-constructor和copy-assignment都声明为delete,因此它不再可能

auto delegate = os << "input3";