lmi
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [lmi] Some std::filesystem usage questions


From: Greg Chicares
Subject: Re: [lmi] Some std::filesystem usage questions
Date: Wed, 23 Sep 2020 22:33:53 +0000
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Thunderbird/68.11.0

On 2020-09-23 19:09, Vadim Zeitlin wrote:
> 
>  Transition from Boost.Filesystem to std::filesystem was mostly painless

That's great news.

> and even pleasant, as it allowed to get rid of some not very pretty code,
> notably we don't need initialize_filesystem() any more.

OTOH, if it was protecting us from anything, we lose that.
But such is progress; and progress on this front must be made.

I almost want to ask whether initialize_filesystem() was
protecting us from what follows...

>  Both problems can be seen with the following snippet:
> 
>       std::cout << (fs::path{"/dir/subdir"} / fs::path{"filename"}) << "\n";
> 
> The output, under MSW, is
> 
>       "/dir/subdir\\file.name"
> 
> which shows both of the issues:
> 
> 1. We get an ugly mixture of slashes and backslashes, as any slashes
>    present in the source code remain, but operator/() uses the native
>    path separator, i.e. a backslash under MSW.
> 
> 2. Backslashes are doubled and the entire path is double quoted because
>    operator<<(std::ostream, fs::path) uses std::quoted() by default in
>    order to round-trip paths with spaces in them successfully and this
>    is the result.

How grotesque! I've been watching maxillary sinus floor augmentation
videos, but "/dir/subdir\\file.name" is more painful to look at.

The One True Path Separator is '/'. (I have an opinion about CRLF, too.)
And we'll quote things as we please.

>  If we want to have some nicer output, e.g. in error messages, we first
> need to decide what kind of output do we want

We want what origin/master does today, because it's perfect as is.
IIRC, boost-1.33.1 didn't provide an inserter, so 'path_utility.hpp'
does [reformatted here for brevity]:

namespace boost{ namespace filesystem{
  inline std::ostream& operator<<(std::ostream& os, fs::path const& z)
    {return os << z.string();}
} }

I suppose we shouldn't try to define that in ns std, but isn't there
a way to make it work as though we had? Brutally, using...

> generic_string() for string conversion

...would do so, as you note below:

- os << somepath
+ os << somepath.generic_string()

but I hope there's some elegant way to force our own

  inline std::ostream& operator<<(std::ostream& os, std::filesystem::path 
const& z)
    {return os << z.generic_string();}

to take precedence over whatever the standard library provides.

>  So I think there are 3 reasonable choices:
> 
> 0. Do nothing
> 1. Embrace the dark side

No, and never. (You never watched those Star Wars movies, or you wouldn't ask.)

> 2. Stick to POSIX conventions

Yes.

>    and use "oss << path.generic_string()". This
>    still suffers from a similar problem as the previous solution, i.e. we'd
>    need not only add all these calls to generic_string() right now, but
>    also keep not forgetting to add them in the future.

Okay. If the standard operator<<() can't tidily be overridden,
then this works. I don't think we'd forget, and if we ever do,
it's just an aesthetic problem that will be liquidated on sight.

To be sure we get it right when we upgrade to std::filesystem,
perhaps removing the code above from 'path_utility.hpp' first
would turn every use into an error, so we couldn't fail to
do this in every case:

- os << somepath
+ os << somepath.string()

Then we do the upgrade, and they're all errors again, so we
do this:

- os << somepath.string()
+ os << somepath.generic_string()

and then everything has to be correct, I think.


reply via email to

[Prev in Thread] Current Thread [Next in Thread]