Subject: Re: [boost] [Filesystem] v3 path separator changes
From: Alexander Lamaison (awl03_at_[hidden])
Date: 2013-03-24 14:03:06
Rob Stewart <robertstewart_at_[hidden]> writes:
> On Mar 23, 2013, at 12:13 PM, Alexander Lamaison <awl03_at_[hidden]> wrote:
>> Beman Dawes <bdawes_at_[hidden]> writes:
>>> On Sat, Mar 16, 2013 at 12:54 PM, Alexander Lamaison
>>> <awl03_at_[hidden]> wrote:
>>>> I'm manipulating Unix paths for use over SFTP, but doing so on Windows.
>>>> For instance I might want to append "c" to the Unix path "/a/b".
>>>> path p("/a/b");
>>>> p /= "c";
>>>> cout << p.string();
>>>> In version 2 this would output "/a/b/c" but now it produces "/a/b\c".
>>>> Why the breaking change?
>>> IIRC, it was partially requests from users and partially the
>>> realization that most users want platform independent syntax but
>>> platform dependent semantics.
>> In that case I'd expect it to output "\a\b\c". I can't think of a
>> reason why mixed slashes would ever be the right answer. It's the
>> worst of both worlds.
> You're expecting this line
> path p("/a/b");
> to parse your string into "a" / "b" when it merely stores the string
> as you gave it.
That's not true. It does parse the string and recognises "a" and "b" as
separate segments of the path. If it didn't, iteration would return
"a/b" followed by "c". I wrote a small program (included at the end) to
prove this. Here is the output:
> Otherwise, when you add this line
> p /= "c";
> you expect the previous separator to be used rather than the native
> separator it uses.
I expect the path to abstract over the separators used and, when asked
for the path as a string, return something consistent. It doesn't
matter if that means always using the native separator, as long as it
doesn't use both.
>> But, the biggest issue is that the change wasn't documented. The
>> docs make a big deal of the change from templated paths to a single
>> path class, but make no mention of this, more significant,
> I can't imagine that Beman would reject a documentation patch.
I'll fix the documentation once I understand the reasoning.
>>> If you would rather continue to use operator /= then change the output to
>>> cout << p.generic_string();
>> I've since discovered this string/generic_string/native triplet. I
>> don't think it's the right solution. string() should either return
>> the generic string or the native string. What it returns at the
>> moment is confusing and not very useful. Or is there a use-case I'm
>> not seeing.
> string() is returning the contents, as you instructed path to form
> it. Calling generic_string() means parse the contents and ensure all
> separators follow the generic syntax.
Constructing a path from "a/b" isn't an instruction to the library to
construct a path with forward slashes. It's an instruction to create a
path abstraction with two segments, the first "a" and the second "b".
Separators shouldn't even come into it until a string representation of
the path is requested, and the string conversion methods should make
explicit what separator to use: generic or native.
> To do what you want would require path to be modal.
I don't undestand what you mean here.
> Marking it, in this case, to do everything in the generic format first
> would have given the behavior you wanted. However, there is no such
> modality. / appends with the native separator. Construction from a
> string, or appending one, merely stores the supplied string. When you
> want a specific format after mixing those operations, call
> generic_string() or native_string().
Again, this isn't true. / appends a segment. Separators are irrevant
to a path abstraction. In version 2 this was the case. v3 muddles
it by giving seperators extra significance.
#define BOOST_FILESYSTEM_VERSION 3
cout << "Enter path: " << endl;
cin >> path_string;
cout << "string(): " << p.string() << endl;
cout << "generic_string(): " << p.generic_string() << endl;
cout << "native(): ";
wcout << p.native();
cout << endl;
cout << "Segments: " << endl;
path::iterator i = p.begin();
while (i != p.end())
cout << "\t" << *i++ << endl;
cout << endl;
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk