filesystem headers
Hi, I found the filesystem headers to be very confusion, the grouping of classes and functions into headers seems to have been chosen arbitrary. basic_recursive_directory_iterator in convenience.hpp? basic_directory_iterator in operations.hpp? shouldn't they use headers of their own, or at least use filesystem/iterator.hpp ? create_directories is in convenience.hpp, but create_directory in operations.hpp? the free function extension(path) is in convenience.hpp, although I think most users would expect it to be a member of the basic_path class instead. a rather highlevel (IMO) function copy_file is in operations.hpp, while others like change_extension is in convenience.hpp. what should I expect to find in convenience.hpp that is not in operations.hpp? basic_filesystem_error, which is an std::exception derived class is in path.hpp, shouldn't it go into exceptions.hpp? maybe someone could shed some light on how I should understand the api in order to include the correct header.. More about path.hpp.. I think the use of iterator_facade in path.hpp is unfair to users, since it pulls in so much of complicated headers (have a look at iterator_facade.hpp) only to ease the task of implementing that path::iterator. I think that iterator_facade is a great tool for users that quickly wants to design a working iterator, but in a header such as filesystem::path that -should- be used everywhere where a file reference is needed, it should be rather lightweight (instead we use std::string, because it compiles with reasonable speed. I think we are not alone on this choice). The inclusion of iosfwd only for stream operators is again not what I would prefer, better off putting that stuff in path_io.hpp is type_traits/is_same.hpp, throw_exception.hpp, static_assert.hpp used in path.hpp at all? Sorry for all the complains, I wouldn't write them unless I really, really wanted to use boost::filesystem. Finally there's a better way to do file and path operations in c++, but it's not practical in its current form. I've been trying with no success incorporating filesystem more in our very large code base, but compilation times and confusion about headers have made me redraw most of that code. Regards, Christian
I have to second pretty much everything said in this post. I have
found the boost::filesystem headers quite heavy. In my own code I do
use boost::filesystem because its portability is important, however I
use it as implementation detail. I've made that decision for two
reasons:
First, I find the separation between path and wpath unfortunate. I
much prefer the simpler utf8 encoding.
Second, for me it is unacceptable (showstopper really) to include this
much code just to be able to say in a header file:
void foo( boost::filesystem::path const & );
My solution is to use std::string to store paths and to define path
interfaces, and use wrappers that forward the call to
boost::filesystem, like so:
bool
create_directory( std::string const & s )
{
return create_directory(wpath(utf8_decode(s)));
}
Of course, having the type system reflect the fact that a string is
not just a string but is really a file path is a good thing, but
compare the boost::filesystem headers to something like this:
#include <string>
#include
Hi,
I found the filesystem headers to be very confusion, the grouping of classes and functions into headers seems to have been chosen arbitrary.
basic_recursive_directory_iterator in convenience.hpp? basic_directory_iterator in operations.hpp? shouldn't they use headers of their own, or at least use filesystem/iterator.hpp ?
create_directories is in convenience.hpp, but create_directory in operations.hpp? the free function extension(path) is in convenience.hpp, although I think most users would expect it to be a member of the basic_path class instead.
a rather highlevel (IMO) function copy_file is in operations.hpp, while others like change_extension is in convenience.hpp. what should I expect to find in convenience.hpp that is not in operations.hpp?
basic_filesystem_error, which is an std::exception derived class is in path.hpp, shouldn't it go into exceptions.hpp?
maybe someone could shed some light on how I should understand the api in order to include the correct header..
More about path.hpp.. I think the use of iterator_facade in path.hpp is unfair to users, since it pulls in so much of complicated headers (have a look at iterator_facade.hpp) only to ease the task of implementing that path::iterator. I think that iterator_facade is a great tool for users that quickly wants to design a working iterator, but in a header such as filesystem::path that -should- be used everywhere where a file reference is needed, it should be rather lightweight (instead we use std::string, because it compiles with reasonable speed. I think we are not alone on this choice). The inclusion of iosfwd only for stream operators is again not what I would prefer, better off putting that stuff in path_io.hpp is type_traits/is_same.hpp, throw_exception.hpp, static_assert.hpp used in path.hpp at all?
Sorry for all the complains, I wouldn't write them unless I really, really wanted to use boost::filesystem. Finally there's a better way to do file and path operations in c++, but it's not practical in its current form. I've been trying with no success incorporating filesystem more in our very large code base, but compilation times and confusion about headers have made me redraw most of that code.
Regards, Christian _______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
[Please do not mail me a copy of your followup] I have been using filesystem, but in my code I hadn't noticed the compile time cost. However, I see your point. Have you filed a bug report on the heavy compile-time cost of using filesystem? -- "The Direct3D Graphics Pipeline" -- DirectX 9 draft available for download http://www.xmission.com/~legalize/book/download/index.html Legalize Adulthood! http://blogs.xmission.com/legalize/
Christian Holmquist wrote:
Hi,
I found the filesystem headers to be very confusion, the grouping of classes and functions into headers seems to have been chosen arbitrary.
basic_recursive_directory_iterator in convenience.hpp? basic_directory_iterator in operations.hpp? shouldn't they use headers of their own, or at least use filesystem/iterator.hpp ?
create_directories is in convenience.hpp, but create_directory in operations.hpp? the free function extension(path) is in convenience.hpp, although I think most users would expect it to be a member of the basic_path class instead.
a rather highlevel (IMO) function copy_file is in operations.hpp, while others like change_extension is in convenience.hpp. what should I expect to find in convenience.hpp that is not in operations.hpp?
basic_filesystem_error, which is an std::exception derived class is in path.hpp, shouldn't it go into exceptions.hpp?
maybe someone could shed some light on how I should understand the api in order to include the correct header..
I agree that the separation of functions to headers, as you describe above, does not seem very logical. Probably it's better to include all headers.
More about path.hpp.. I think the use of iterator_facade in path.hpp is unfair to users, since it pulls in so much of complicated headers (have a look at iterator_facade.hpp) only to ease the task of implementing that path::iterator. I think that iterator_facade is a great tool for users that quickly wants to design a working iterator, but in a header such as filesystem::path that -should- be used everywhere where a file reference is needed, it should be rather lightweight (instead we use std::string, because it compiles with reasonable speed. I think we are not alone on this choice).
Do you have hard numbers about how much the user of iterator_facade affects compilation speed? Honest question -- I also find it unfortunate that compilation time is not a priority for Boost. - Volodya
Do you have hard numbers about how much the user of iterator_facade affects compilation speed? Honest question -- I also find it unfortunate that compilation time is not a priority for Boost.
- Volodya
I second that -- I am quite curious about how much overhead various headers/libraries impose when you include tham, and when you actually use them (which seems to be a lot more expensive on msvc). Quick compile-test-correct cycles are important to me. I don't know the best way to even measure this. In my code path and iterator_facade are both used a lot in my own interfaces and if they are costing me significant build time I will switch to just string/std::iterator in my headers. -- John
On Thu, May 29, 2008 at 8:16 AM, John Femiani
I second that -- I am quite curious about how much overhead various headers/libraries impose when you include tham, and when you actually use them (which seems to be a lot more expensive on msvc). Quick compile-test-correct cycles are important to me. I don't know the best way to even measure this.
In my opinion it is pointless to measure compile times. Instead,
headers should be designed in a way that allows user code to not "see"
anything that is not strictly necessary to compile a particular user
cpp file.
Back to boost::filesystem, I see two problems:
- It uses very few headers which makes it impossible to #include a
small bit of it.
- The path and wpath types are in fact typedefs of the basic_path
template and this makes using incomplete path references rather
clunky. One has to write:
#include <string>
namespace boost
{
namespace filesystem
{
template
Emil Dotchevski wrote:
wrote: I second that -- I am quite curious about how much overhead various headers/libraries impose when you include tham, and when you actually use them (which seems to be a lot more expensive on msvc). Quick compile-test-correct cycles are important to me. I don't know the best way to even measure this.
In my opinion it is pointless to measure compile times. Instead, headers should be designed in a way that allows user code to not "see" anything that is not strictly necessary to compile a particular user cpp file.
So are you recommending that path should not be part of a public interface, since a path can be represented by a string? Or are you saying that it is not worth measuring the cost of all-header libraries that include too much per header since they should be refactored anyways? -- John
On Thu, May 29, 2008 at 1:45 PM, John Femiani
Emil Dotchevski wrote: In my opinion it is pointless to measure compile times. Instead, headers should be designed in a way that allows user code to not "see" anything that is not strictly necessary to compile a particular user cpp file.
So are you recommending that path should not be part of a public interface, since a path can be represented by a string?
Or are you saying that it is not worth measuring the cost of all-header libraries that include too much per header since they should be refactored anyways?
I am sorry, pointless was perhaps too strong of a word there. My point is that while my concerns do have something to do with compilation times, this is somewhat secondary to my desire (in principle) to lower the level of coupling (in boost::filesystem in particular) even if it had no effect on compilation times. -- Emil Dotchevski Reverge Studios, Inc. http://www.revergestudios.com/reblog/index.php?n=ReCode
On Wed, May 28, 2008 at 11:15 PM, Vladimir Prus
Christian Holmquist wrote: Do you have hard numbers about how much the user of iterator_facade affects compilation speed? Honest question -- I also find it unfortunate that compilation time is not a priority for Boost.
The biggest issue for the coupling in Boost is that most libraries are header-only. While this makes them easier to adopt, it also makes talks about reducing physical coupling almost pointless. Yes, there are templates, but even within "templated" code there are plenty of pieces that don't depend on T and can and should be separated into a .CPP file. The other thing is that even if there is pressure from the users to fix this problem, it is perhaps too late. Like John Lakos points in his excellent book, when reducing physical coupling is your top priority, it significantly affects your overall design, and for most of the Boost libraries the design is but set in stone. -- Emil Dotchevski Reverge Studios, Inc. http://www.revergestudios.com/reblog/index.php?n=ReCode
2008/5/29 Vladimir Prus
Christian Holmquist wrote:
Do you have hard numbers about how much the user of iterator_facade affects compilation speed? Honest question -- I also find it unfortunate that compilation time is not a priority for Boost.
I haven't modified fs::path to not use iterator_facade and measured the difference, no. It could be other sources that affects the compilation time as well, I'll try to put together a test in the weekend. Still fs::path depends on complicated libraries compared to std::basic_string, when they're both merely a wrapper around a char type with a traits class. If std::basic_string only had the 'path concatenation' operator/ (which I found very useful), would there be any use for fs::path? when it comes to the member functions of fs::path, it seems like they're going down the road of std::basic_string: a group of member functions that suits some particular usecases, but in the end everyone must revert to free functions doing the real work. I'm now more into extracting the fs::path.append into a free function range append_path(range, range, path_traits) then I could manually overload operator/ for std::basic_string and get the nifty path / path. With a wrapper header like the one Emil Dotchevski suggested for file operations there'd be close to no penalty for filesystem dependent code. - Christian
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
participants (5)
-
Christian Holmquist
-
Emil Dotchevski
-
John Femiani
-
legalize+jeeves@mail.xmission.com
-
Vladimir Prus