vendredi 20 juillet 2018

How to have "factory function" return a non copyable object ?

Context

Trying to create some gzip archive with a different filename inside I wrote this following snippet of code.

#include <iostream>
#include <utility>

#include <boost/iostreams/filtering_stream.hpp>
#include <boost/iostreams/device/file.hpp>
#include <boost/iostreams/filter/gzip.hpp>

boost::iostreams::filtering_ostream&& makeGZipStream(const std::string& archiveName,
                                                     const std::string& fileName)
{
    boost::iostreams::filtering_ostream theGzipStream;

    boost::iostreams::gzip_params theGzipParams;

    theGzipParams.file_name = fileName;

    theGzipStream.push(boost::iostreams::gzip_compressor{theGzipParams});

    theGzipStream.push(boost::iostreams::file_sink{archiveName});

    return std::move(theGzipStream);
}

int main()
{
    boost::iostreams::filtering_ostream&& theGzipStream = makeGZipStream("archive.gz", "file");

    theGzipStream << "This is a test..." << std::endl;

    return 0;
}

Problem

This (as we may expect) produces a core dump because in makeGZipStream we try to return a local stack-allocated variable by (rvalue-)reference. But the copy was not an option in this case as boost::iostreams::filtering_ostream is non-copyable.

Questions

  1. We can return a std::unique_ptr by value thanks to copy-ellision, why isn't it possible in this case ?
  2. What are the good solutions there ?

Possible solutions

  1. Putting everything in the same scope (what I was trying to avoid)
  2. Wrapping your object in a unique_ptr (not so pretty)
  3. Anything else ?

Notes

The compiler used was the quite old g++ (GCC) 4.9.3.

Aucun commentaire:

Enregistrer un commentaire