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?
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.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With