
On Friday 25 January 2013 23:55:19 Yakov Galka wrote:
On Fri, Jan 25, 2013 at 6:49 PM, Andrey Semashev
<andrey.semashev@gmail.com>wrote:
[...]
IMHO, path should not pretend to be a container. Things like push_back, insert, erase don't make sense with respect to it. It could provide begin/end iterators over underlying characters but just to implement other algorithms. Iterating over path elements (i.e. what is currently achieved with begin/end) should probably be an external tool, like an iterator adaptor or a view on top of the path object. In the end it should become just a thin wrapper over a string, with a few path-related functions.
What are those path-related functions that you will leave there? extension()? has_root()? Maybe these are also better to be free standing functions working on arbitrary strings?
Which functions to leave as members and which to extract as free functions is a design choice. I would probably leave operations that have meaning of accessing parts of the path (like filename, extension, parent path, etc.) as members and extract everything else.
You are left with operator/, which also can be declared as
string operator/(const string&, const string&);
and be brought to scope with a using directive, for those who want to use it.
operator/ doesn't make sense for strings, it should never be defined like that. Whether it is defined as a member function or a free function is not essential, but it should be specific for paths.
Essentially you are left with a plain old string of a platform dependent encoding. This is what I said in my first post—thinking that "a path as a string" is applicable where you don't care for what is inside the path (in which case just use a string as a cookie), but in other cases it is nonsense.
Well, most of the time all I want is a wrapper around a string that conceals platform-specific filesystem differences, nothing more. So yes, a path is a plain old string with a few helpers to compose and interpret it in a portable way. And I don't need anything more sophisticated from it. Another part of the library is a set of algorithms to operate on the actual filesystem (like, copying the files and testing for path equivalence); this part is also required and very useful. These algorithms abstract away another aspect of the filesystem (namely, the underlying OS API) and they don't need anything sophisticated from the path either. Interestingly, most of these algorithms can operate with plain strings instead of paths. So basically, the path does not need to be a high-level beast to be useful. That does not mean that such high-level tools are useless, but they can be implemented externally, without cluttering the path interface.
So please explain why "path should not pretend to be a container".
I think I've answered this partially above. I'll add that a container is supposed to contain elements and I'm not sure what is supposed to be an element of a path. A path is basically an identifier for a file, which is a more or less indivisible entity. Surely you can introspect its contents, but these parts either won't be a path (e.g. extension) or will be a path identifying another file (e.g. parent path).
I agree in general that implementing a view for iterating over path elements is an acceptable strategy, though. But in this case it is better to scrap the path class completely.
I disagree. Path type is very useful, if not for its operations then for type clarity at the very least.