Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bump to C++17 for std::filesystem #53

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

franklange
Copy link

@franklange franklange commented Mar 26, 2021

Exchanges the current use of std::string or boost::filesystem with std::filesystem::path as initiated by this issue: #51

This is a rather mechanical refactoring and I tried to change as little as possible besides the types.
I also have a follow up PR in the pipeline that does the same for std::optional, so let me know what you think :)

Edit 1:
I didn't do the change in

  • avassetreader_source
  • ogg_source

because I wasn't sure if that would be desirable. Please let me know if those should be adjusted as well.

@@ -38,7 +40,7 @@ class aiff_ofstream : public ofstream
aiff_ofstream( aiff_ofstream&& );
aiff_ofstream& operator=( aiff_ofstream&& );

aiff_ofstream( const std::string& file, const info_type& info );
aiff_ofstream( const std::filesystem::path& file, const info_type& info );

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can break existing code. If a user passes an argument of a type that can implicitly convert to std::string, it might not work if the signature now expects a std::filesystem::path. See https://gcc.godbolt.org/z/49x1vKMEq.

How about overloading instead of replacing?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for bringing this up! I didn't consider this tbh. Though I'm slightly more okay with this being a breaking change but that's of course not up to me :)

Would it be acceptable if users that are affected by this adjust like this?
https://gcc.godbolt.org/z/KaTca6o19

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 for overloading, not everybody is ready to use std::filesystem, yet. Imho it should mirror the ctors of: https://en.cppreference.com/w/cpp/io/basic_fstream/basic_fstream
In order to fix the bug, it is important that you can pass in a std::wstring instead of a std::string on Windows.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Heyhey, thanks for the feedback!

In order to fix the bug, it is important that you can pass in a std::wstring instead of a std::string on Windows.

Not sure I agree with the overload though because isn't this exactly what fs::path is trying to solve?

But in any case, just to make sure I understand what you guys are suggesting, it would be something like this?
https://godbolt.org/z/86cPTd95o

In other words: platform macro for string/wstring and additionally a template overload for path because naive overloading doesn't work?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess this is ultimately up to the maintainers, but here's my opinion: I think having a constructor for a std fs path is a good idea. I would try to avoid breaking changes because they might annoy users. In your approach, the point of the template is so that when passing a const char*, the compiler does not consider the fs path ctor?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I basically took this from the mentioned fstream overload implementation:
fstream string + path overload

I think in this particular case I disagree with trying to avoid a "breaking" change because:
a) somehow I don't see how it makes sense from a library's perspective to offer a string and a path ctor other than for backwards compatibility reasons but maybe I'm still missing something and
b) it only affects those clients that defined an implicit conversion operator to string for their type and all they'd have to do to fix this would be to change the operator to fs::path. It's actually sort of weird that the compiler can't figure out the transitivity on its own from type -> string -> lib(path) and just needs some slight help here.

But ya, I can only open the PR :)


namespace audio
{

// a map of extension => container type
using ifstream_container_map = std::map<std::string, ifstream_info::container_type>;
using ifstream_container_map = std::map<std::filesystem::path, ifstream_info::container_type>;
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here I wasn't sure if this might be overkill but motivation was that extensions are also paths.

@@ -43,34 +43,33 @@ namespace
bool init()
{
#if BOOST_OS_WINDOWS
boost::filesystem::path::imbue( std::locale( std::locale(), new std::codecvt_utf8_utf16<wchar_t>() ) );
std::filesystem::path::imbue( std::locale( std::locale(), new std::codecvt_utf8_utf16<wchar_t>() ) );
Copy link

@C4rsten C4rsten Mar 27, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

std::filesystem::path::imbue() does not exist.
It's better to not rely on string conversions, but instead always use the native string format.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here I wasn't even sure what this is all about. Could you elaborate why this needed?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

boost::filesystem::path::imbue sets the path locale for boost::filesystem. Using the std::codecvt facet sets up the proper conversion between UTF8 and UTF16 characters. This is needed on Windows for setting up a proper string conversion, as Windows uses a locale based on the system settings. Leaving the locale up to Windows results in conversions when the paths have special characters possibly failing (consider Japanese and Chinese characters on a western system).

See: https://stackoverflow.com/questions/45572209/getting-a-boostfilesystempath-as-an-utf-8-encoded-stdstring-on-windows

Note: std::codecvt has been deprecated so this isn't a futureproof solution.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Switch to a path interface instead of using std::string for file paths
4 participants