
I propose the following design. The aim of boost::filesystem should be to support the following coding idiom: * The programmer should take care to only handle two types of paths in his application: 1) Complete paths 2) Relative paths * The programmer will have to specifically tell the libary when a constructed path is 'native' and when not. A native path is accepted according to native rules and never gives any problem (exceptions) further on. A non-native path is checked according to the existing rules, which basically means that the programmer can set a default check routine that will in effect determine how portable the application will be. I propose two design changes: 1) 'native' is now not only a representation, but an *internal state* of fs::path. (this has no effect on the representation as returned by fs::path::string()). 2) All 'complete' paths are automatically marked as 'native'. Examples, the following code is legal: fs::path p1("C:\foo\a.exe", native); // Fails on linux, success on windows. fs::path p2("/usr/src/a.out, native); // Fails on windows, success on linux. std::cout << p1.native_file_string(); // ok, p1 is native. fs::path p3("foo/bar"); // Relative path, always succeeds. std::cout << p.string(); // ok std::cout << p.native_directory_string(); // Useless, but ok. fs::path p4(complete(p3)); // p4 is now "native", because now it is complete. std::cout << p4.native_directory_string(); // ok And the following will throw: std::cout << p4.string() // Not allowed because p4 is native (complete). Since there would be a default way defined of how a relative path is completed, all operation functions will accept both, relative and complete paths. For example: fs::path p1("C:\cygwin\usr/bin/ls", native); // Legal path on Cygwin. if (fs::exists(p1)) // Ok, access complete path. // For clarification fs::path p2("C:\cygwin\usr"); // Just an example fs::default_working_directory(p2); // fictuous function. fs::path p3("bin/ls"); // Portable representation (refers in fact to "C:\cygwin\usr\bin\ls.exe"). if (fs::exists(p3)) // Ok : exists() will make the path complete before testing. And this throws: fs::path p4("/bin/ls"); // Not allowed: this path has a root but is not marked 'native'. Setting the default_working_directory shall allways need to be done for each supported OS seperately. Of course you can set it to "/" on single root machines, and set it to "E:/" after extracting the 'E:' from the current path at application start up, in effect simulating a 'single root': int main() { fs::default_working_directory(fs::current_path().root_path()); // ... simulate single root machine below. fs::path p("bin/ls"); } The average application will work with relative paths, relative to some (native) base directory and next to that have some arbitrary, complete and thus native directories (ie, read from environment variables). But in case more than one 'working' directory seems needed then we can add support for that too by allowing to construct paths with a reference to the (complete/native) working directory. Ie, fs::path home_base(...); // ... fs::path runtime_rcfile(home_base); // ... runtime_rcfile = "myapplication/config/runtime/rc"; which is then relative to `home_base' instead of a single, global 'working directory' (as now returned by fs::current_path()). Most of the current boost::filesystem API can be preserved with this design. -- Carlo Wood <carlo@alinoe.com>