I was surprised to find that the following code does not compile:
auto example_function(std::string_view filename) {
std::fstream ofile(filename, std::ios_base::out | std::ios_base::binary);
std::fstream ifile(filename, std::ios_base::in | std::ios_base::binary);
}
Both of these lines produce similar errors:
error: no matching function for call to ‘std::basic_fstream<char>::basic_fstream(std::string_view&, std::_Ios_Openmode)’
error: ‘class std::basic_string_view<char>’ has no member named ‘make_preferred’
= decltype(std::declval<_Path&>().make_preferred().filename())>
error: no matching function for call to ‘std::basic_fstream<char>::basic_fstream(std::string_view&, std::_Ios_Openmode)’
error: ‘class std::basic_string_view<char>’ has no member named ‘make_preferred’
= decltype(std::declval<_Path&>().make_preferred().filename())>
The constructor options include arguments of type const char* and std::string&.
I was surprised to find no option includes std::string_view. Is there any obvious reason why this was not included?
Is there a valid way to make this code compile? Converting from a std::string_view to const char* may not be particularly safe, since a std::string_view may not be null terminated at the end of its .size().
Creating a std::string, on the other hand, will cause an additional copy and allocation.
The C++ committee explicitly decided that fstream should not be constructible from string_view: The underlying OS call needs a null-terminated string, an allocation is required to turn a string_view to a null-terminated string, and the committee wants this allocation to be explicit (instead of implicit in the fstream construction).
In 2017, std::fstream was actually made constructible from std::string_view, because they are constructible from std::filesystem::path, and the latter is convertible from std::string_view. But this is considered a defect in C++17, and got banned by LWG 3430.
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