代码之家  ›  专栏  ›  技术社区  ›  Antonio Dropulić

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

  •  1
  • Antonio Dropulić  · 技术社区  · 6 年前

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

    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();
    }
    

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

    此外,我在代码中看到了一个可能的陷阱。I如下代码所示:

    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 析构函数的方式与 StreanDelegate ,但我可能希望这对单身汉有效。

    1 回复  |  直到 6 年前
        1
  •  1
  •   super    6 年前

    我认为你使用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 作为删除,因此无法再执行

    auto delegate = os << "input3";