0

I am designing an interface for reading and writing video frames to various inputs and outputs. Stream operators seem to me a superb alternative to named functions for the task. This is the gist of it:

struct FrameSource
{
    virtual FrameSource & operator>>( cv::Mat & frame ) = 0;
    virtual ~FrameSource() = default;
};

struct FrameSink
{
    virtual FrameSink & operator<<( const cv::Mat & frame ) = 0;
    virtual ~FrameSink() = default;
};

Now, supposing this is an OK design, how should I signal end of stream (end of video; last picture in the folder; deinitialized camera)?

The options I have considered:

  • EndOfIteration exception, like in python. Sounds slow, dangerous and not idiomatic. No way to indicate this behaviour in the header.
  • Return cv::Mat{}. Sounds slow, easy to miss(leading to infinite loops), violates the invariant that any frame can be returned, not idiomatic.
  • cv::Mat f; while(stream.get(f)); idiomatic but involves named functions, return status easy to miss.
  • A variation of the above via the conversion operator operator bool() const;.
  • Derive from std::basic_i/ostream. But those are character based.
  • Derive from iterator and provide begin(), end().

My application doesn't mandate streams, I am using them because of the subjective advantages of:

  • ease of use
  • not having to hold a bunch of large files in working memory simultaneously.
  • Do you need to distinguish between end-of-stream and error? – Christian Hackl Feb 20 '19 at 12:08
  • @ChristianHackl yes, I am using a simple struct Exception : public runtime_error {}; for the latter. – Vorac Feb 20 '19 at 12:13
  • You mention the advantage "not having to hold a bunch of large files in working memory simultaneously". This has absolutely nothing to do with using stream-operators vs using named functions: A stream-operator is still a function call, just like a named function, so both methods can achieve exactly the same things. – pschill Feb 22 '19 at 8:22
  • @pschill streams as opposed to an iterable vector. – Vorac Feb 22 '19 at 8:24
  • @Vorac You can program something that behaves like a stream even if you use named functions instead of the stream operators. I think that helps the user to understand what happens and allows you to use additional arguments (e.g., a bool& end_of_stream argument which cannot be ignored like a return value). If you really want to stick to operator<< and operator>>, you should probably use them in a standard-fashion: Provide some operator bool() which allows the common while (stream >> value) pattern. – pschill Feb 22 '19 at 8:31
1

If you want to provide a stream-like interface, I would strongly recommend to provide an interface that is comparable to that provided by std::basic_i/ostream. For error reporting (including EOF), this would involve the member functions operator! and operator bool (which in std::basic_i/ostream are based on the member functions good, eof, fail, bad).

|improve this answer|||||
  • 3
    Isn't the standard I/O streams interface known to be hard to use and overly complicated? The difference or relationship between good, eof, fail and bad are especially hard to grasp and memorise, and the names are really bad (IMO). For the sake of simplicity, it might be better if the OP just provided operator bool, because that seems to be enough for his use case. – Christian Hackl Feb 20 '19 at 12:14

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.