
Yes, the predicates do throw exceptions, and if you don't want that behavior, you would have to use the status functions. The thought is that it providing non-throwing versions of each of the status functions isn't worth the added convenience. I'm already worried about the size of the library.
I am not worried about the exceptions. What worries me is that it is not clear which functions will throw and when. When I first started to use the library a long time ago I got the impression that exceptions were rare and came from filesystem corruption and racing conditions. Over time I have learned that filesystem exceptions are common and happens all the time also for trivial operations like exists and directory iterations in a perfectly helthy environment. When reading the new documentation I still get the same impression. Exceptions are mentioned together with std::bad_alloc and "cannot successfully complete their operational specifications". Examples don't show exceptions or as in "simple_ls.cpp" only handle them in random places without explanations.
- What happens if an error occurs while iteratoring a directory
There is a non-throwing constructor available, but currently operator++ does not have a non-throwing version.
No problem, just say in the documentation that operator++ might throw. (unfortunatly it makes the non-throwing constructor kind of useless since you still need a try/catch)
or when the recursive iterator can't descend into a sub-folder.
That case is treated as an empty sub-folder.
OK
2. Why not include the system_error code in the file_status object?
Turn the question around. Why would it be desirable to include a system_error code in the file status? I'm not seeing any real advantage - perhaps I'm missing something?
You get both the status and the system error from the same function. Why not keep them together so you don't have to use two variables all the time. I get a feeling that you still think exceptions are rare and that is not common to write code to handle or avoid them.
If you provide "system_error_code nothrow;" somewhere, then you can already write that. All we are talking about is the spelling of "nothrow", it seems to me.
No, I'm trying to avoid extra variable declarations that I think make the code more difficult to understand. Using std::nothrow make the intention clear. Using a variable named nothrow will only add confusion.
3. Why not differentiate storage type and interface type in the basic_path class?
Not sure what you mean. Could you give an example?
The path need a storage type with some requirements (basic_string interface?). I don't see why the interface must use the same type. Lets say I want to store a path in shared memory and use a string with an shmem allocator. The effect is then that I can only use operations on the path with strings stored in the same memory area. In short: Let the constructor, assign and operators always work on basic_string types regardless of what the storage type is. something like template <class TratitsT, class AllocatorT> basic_path(basic_string<CharT, TraitsT AllocatorT>& str) : m_path(str.begin(), str.end()) { }