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

Adding a new line after std::ostream output without explicitly calling it

下面的例子最能说明我的问题:

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() 的 return 值被分配给一个变量,StreamDelegate 没有被破坏,因此没有期望的行为。

我不打算将 Stream::getStream() 分配给一个变量,但如果有办法解决这个问题,我想知道。

我也知道我可以通过以与 StreanDelegate 相同的方式实现 Stream 析构函数来避免 StreamDelegate,但我可能希望它在单例上工作.

我认为你使用 RAII 的想法很好。如果你为你的 Stream 实现模板化 operator<< 并且让 return 你的 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 为删除,所以不再可能

auto delegate = os << "input3";