How do I check if a StringStream variable is empty/null?

前端 未结 8 865
粉色の甜心
粉色の甜心 2020-12-13 08:32

Just a quick question here guys. I\'ve been searching to no avail so far.

A bit more info here:

stringstream report_string;

report_string << \         


        
8条回答
  •  悲哀的现实
    2020-12-13 09:16

    How about another approach?

    If you make the ostringstream an optional type you can check that its been assigned to before using it.

    Imagine a class called lazy<> which lazily constructs an object when needed, then we could do this:

    int main()
    {
        using namespace std;
    
        auto oss1 = lazy();
        auto oss2 = lazy();
    
        use(oss1) << "Hello";
    
        if (oss1) cout << use(oss1).str() << endl;
        if (oss2) cout << use(oss2).str() << endl;
    
        if_used(oss1, [](auto& ss) { cout << ss.str() << endl; });
        if_used(oss2,
                [](auto& ss) { cout << ss.str() << endl; },
                [](auto& oss) { cout << "oss2 is not used" << endl; });
    
        use(oss2) << "Goodbye";
        if_used(oss2, [](auto& ss) { cout << ss.str() << endl; });
    
        return 0;
    }
    

    yielding this output:

    Hello
    Hello
    oss2 is not used
    Goodbye
    

    Advantages:

    • no redundant construction of the stringstream when not used.

    • optional provides an exception if the unused stringstream is subsequently used (via const reference)

    Full example below with customisable constructor:

    I've used std::experimental for the optional, but you could just as easily use boost::optional.

    #include 
    #include 
    #include 
    #include 
    #include 
    
    using std::experimental::optional;
    
    namespace detail {
        template
        struct lazy final
        {
            template, lazy>::value > * = nullptr>
            lazy(Con&& con)
            : _constructor(std::forward(con))
            {}
    
            T& get() {
                if (not bool(_opt)) {
                    _opt = _constructor();
                }
                return *_opt;
            }
    
            const T& get() const {
                return *_opt;
            }
    
            bool used() const {
                return bool(_opt);
            }
    
            operator bool() const {
                return used();
            }
    
        private:
            Constructor _constructor;
            optional _opt;
        };
    
        template
        struct default_construct {
            T operator()() const { return T(); }
        };
    
        struct no_action {
            template
            void operator()(T&) const { }
        };
    }
    
    
    template >
    auto lazy(Constructor&& con = detail::default_construct())
    {
        return detail::lazy>(std::forward(con));
    }
    
    template
    auto& use(detail::lazy& l)
    {
        return l.get();
    }
    
    template
    auto& use(const detail::lazy& l)
    {
        return l.get();
    }
    
    template
    void if_used(detail::lazy& l, F&& f, Else&& e = detail::no_action())
    {
        if (l.used())
            f(l.get());
        else
            e(l);
    }
    
    template
    void if_used(const detail::lazy& l, F&& f, Else&& e)
    {
        if (l.used())
            f(l.get());
        else
            e(l);
    }
    
    int main()
    {
        using namespace std;
    
        auto oss1 = lazy();
        auto oss2 = lazy();
    
        use(oss1) << "Hello";
    
        if (oss1) cout << use(oss1).str() << endl;
        if (oss2) cout << use(oss2).str() << endl;
    
        if_used(oss1, [](auto& ss) { cout << ss.str() << endl; });
        if_used(oss2,
                [](auto& ss) { cout << ss.str() << endl; },
                [](auto& oss) { cout << "oss2 is not used" << endl; });
    
        use(oss2) << "Goodbye";
        if_used(oss2, [](auto& ss) { cout << ss.str() << endl; });
    
        return 0;
    }
    

提交回复
热议问题