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: Vadim Zeitlin
Subject: Re: [lmi] Some std::filesystem usage questions
Date: Thu, 24 Sep 2020 01:06:15 +0200

On Wed, 23 Sep 2020 22:33:53 +0000 Greg Chicares <gchicares@sbcglobal.net> 
wrote:

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

 I don't think so, AFAICS the standard library just works differently.

GC> How grotesque! I've been watching maxillary sinus floor augmentation
GC> videos, but "/dir/subdir\\file.name" is more painful to look at.
GC> 
GC> The One True Path Separator is '/'. (I have an opinion about CRLF, too.)
GC> And we'll quote things as we please.

 Note that this means that we'll have to take care of spaces in the path
too, if we ever read them from somewhere, though. I.e. I understand the
decision to quote the output value, even if I'm not sure I agree with it.

GC> We want what origin/master does today, because it's perfect as is.

 It's definitely not perfect in at least one aspect: it mangles non-ASCII
file names. I didn't want to raise this issue right now, but I did want to
return to it later and this was just a too perfect opportunity to let it
pass. So, even though I know that lmi is exclusively US-centric, I still
think it's a good idea to be able to open file names with "©" or similar
non-ASCII symbols used even in the US in their names. So I'd also like to
suggest using UTF-8, as long as we're breaking^W improving things.

GC> IIRC, boost-1.33.1 didn't provide an inserter, so 'path_utility.hpp'
GC> does [reformatted here for brevity]:
GC> 
GC> namespace boost{ namespace filesystem{
GC>   inline std::ostream& operator<<(std::ostream& os, fs::path const& z)
GC>     {return os << z.string();}
GC> } }

 However the standard class does define operator<<() (and also >>) and we
can't opt out from using it, to the best of my knowledge, because it's
always found using ADL as soon as the argument is a std::filesystem::path.

GC> > generic_string() for string conversion
GC> 
GC> ...would do so, as you note below:
GC> 
GC> - os << somepath
GC> + os << somepath.generic_string()
GC> 
GC> but I hope there's some elegant way to force our own
GC> 
GC>   inline std::ostream& operator<<(std::ostream& os, std::filesystem::path 
const& z)
GC>     {return os << z.generic_string();}
GC> 
GC> to take precedence over whatever the standard library provides.

 Maybe you have some better ideas, but the only way I see to do it is to
define our own fs::path as a _wrapper_ around std::filesystem::path, rather
than a synonym for it. This would definitely allow us to define an
operator<<() for it behaving as we want and would also allow us to tweak
its behaviour in other ways.

 Initially I thought that having our own class would be an overkill, but
more I think about having to use generic_string() manually everywhere, more
I like this idea. It's not like there is going to be much code in this
class, after all, and it will be practically indistinguishable from the
standard class anyhow. So, unless you are strongly allergic to this idea,
I'd like to at least try implementing it.

GC> >  So I think there are 3 reasonable choices:
GC> > 
GC> > 0. Do nothing
GC> > 1. Embrace the dark side
GC> 
GC> No, and never. (You never watched those Star Wars movies, or you wouldn't 
ask.)

 No, I didn't. But I feel that I know them well enough even so. You just
underestimate the strength of temptation of the other side.

GC> > 2. Stick to POSIX conventions
GC> 
GC> Yes.

 OK, thanks for confirming this, I rather suspected this would be the case.

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

 We can't really do this, because operator<<() is defined in the standard
header, but we can do something pretty similar by adding

        std::ostream& operator<<(std::ostream&, const fs::path&) = delete;

And this, in fact, exactly how we tested these changes.

 Thanks again for your answer,
VZ

Attachment: pgpb17JRpf5Fo.pgp
Description: PGP signature


reply via email to

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