Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Implicit conversion between std::filesystem::path and std::string, should it happen?

The cppreference page for std::filesystem::path states:

Paths are implicitly convertible to and from std::basic_strings, which makes it possible to use them with over files APIs, e.g. as an argument to std::ifstream::open

Now the conversion to a std::filesystem::path is easy to see as it has a non-explicit constructor that takes std::string types. What I can't seem to find, though, is a way to go to a std::string implicitly.

There is a string function, but it is std::string string() const;, not operator std::string(). Using

#include <filesystem>

void foo(std::string) {}

int main()
{
    namespace fs = std::filesystem;
    fs::path p1;
    foo(p1);
}

this code compiles fine with icc, gcc, and clang, but not with MSVS, where it gives the error:

example.cpp

<source>(10): error C2664: 'void foo(std::string)': cannot convert argument 1 from 'std::filesystem::path' to 'std::string'

<source>(10): note: No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called

Compiler returned: 2

So, which compiler is right? Is there an implicit conversion sequence, or are the compilers just being helpful?

like image 850
NathanOliver Avatar asked Aug 06 '19 13:08

NathanOliver


2 Answers

There is an implicit conversion to std::basic_string<value_type>, where value_type is an OS-dependent character type.

And, (§30.10.8 in my draft copy, n4659)

For POSIX-based operating systems, value_type is char [...]
For Windows-based operating systems, value_type is wchar_t [...]

so there doesn't need to be an implicit conversion to std::string on Windows, only to std::wstring.

like image 58
molbdnilo Avatar answered Oct 18 '22 06:10

molbdnilo


All compilers are right. It is specified by the standard that it should have a conversion to string_type:

operator string_type() const;

Returns: native().

string_type here is:

using string_type = basic_string<value_type>;

And native() :

const string_type& native() const noexcept;

Returns: The pathname in the native format.

Native format being basic_string<value_type>.

value_type however doesn't have to be char and thus the conversion to std::string doesn't always exist. It's only mandated that one to basic_string<>exists.

like image 28
Hatted Rooster Avatar answered Oct 18 '22 06:10

Hatted Rooster