Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why doesn't make_optional work for file streams?

I'm trying out the C++17 optional-type, and thought a fitting place to use it would be a function that attempts to open a file and maybe returns the opened file. The function I wrote looks like this:

std::optional<std::fstream> openFile(std::string path)
{
    std::fstream file;
    file.open(path);
    if (!file.is_open())
    {
        std::cerr << "couldn't open file" << path << std::endl;
        return {};
    }
    else
    {
        return std::make_optional(file); // results in compilation error
    }
}

But when I try to compile this with g++ with -std=c++17 as one of the arguments I get a big wall of template compilation error messages, starting with:

In file included from read_file.cpp:3:0:
/usr/include/c++/7/optional: In instantiation of ‘constexpr std::optional<typename std::decay<_Tp>::type> std::make_optional(_Tp&&) [with _Tp = std::basic_fstream<char>&; typename std::decay<_Tp>::type = std::basic_fstream<char>]’:
read_file.cpp:16:39:   required from here
/usr/include/c++/7/optional:991:62: error: no matching function for call to ‘std::optional<std::basic_fstream<char> >::optional(<brace-enclosed initializer list>)’
     { return optional<decay_t<_Tp>> { std::forward<_Tp>(__t) }; }

Why would it seem as if fstream can't be used with std::optional? Am I approaching this in the wrong way? If optional doesn't support stream-types, does that not limit where the type can be applied?

like image 819
Rasmus Källqvist Avatar asked Dec 11 '22 00:12

Rasmus Källqvist


1 Answers

Your code will try and copy the stream, when you pass it to make_optional. Streams can't be copied, therefore, you need to move it, i.e.,

return std::make_optional(std::move(file));

or simply

return file;

(Depending on the age of the compiler, the latter might not work.)

like image 175
Bert Avatar answered Dec 12 '22 13:12

Bert