[functional] How to avoid a dependency on functional?
Filesystem has a dependency on
2015-01-09 20:42 GMT+01:00 Beman Dawes
Filesystem has a dependency on
in order to supply this: inline std::size_t hash_value(const path& x) { # ifdef BOOST_WINDOWS_API std::size_t seed = 0; for(const path::value_type* it = x.c_str(); *it; ++it) hash_combine(seed, *it == '/' ? L'\\' : *it); return seed; # else // BOOST_POSIX_API return hash_range(x.native().begin(), x.native().end()); # endif }
The problem with this is that functional is a heavy-weight dependency for such relatively minor feature.
See http://www.pdimov.com/tmp/report-develop-3b5a9f4/module-weights.html
Is there any recommended way to avoid the functional dependency?
A good question. For the same reason I am reluctant to implement hash support in Boost.Optional. Regards, Andrzej
Andrzej Krzemienski wrote:
Is there any recommended way to avoid the functional dependency?
A good question. For the same reason I am reluctant to implement hash support in Boost.Optional.
Optional is easier because you can forward-declare just hash<> and then return empty()? 0: hash<T>()( t_ ). Like shared_ptr.hpp does: // hash_value template< class T > struct hash; template< class T > std::size_t hash_value( boost::shared_ptr<T> const & p ) BOOST_NOEXCEPT { return boost::hash< T* >()( p.get() ); }
Daniel James wrote:
I suggested moving hash_fwd into core in another thread.
'core' is not intended to be a repository for forwarding headers. If we want a repository for forwarding headers, we should create one that serves that explicit goal. I already suggested libs/fwd as the place for it. I have no specific objections against hash_fwd being in core. I could even volunteer to maintain it, if need be. In principle though, having hash_fwd in core means having *_fwd in core, and this I would rather avoid.
On 9 January 2015 at 20:27, Peter Dimov
Daniel James wrote:
I suggested moving hash_fwd into core in another thread.
'core' is not intended to be a repository for forwarding headers. If we want a repository for forwarding headers, we should create one that serves that explicit goal. I already suggested libs/fwd as the place for it.
I don't care less what the destination is called. I only said 'core' because that is what we currently have. I think in my other post I said it could be somewhere else.
Beman Dawes wrote:
Filesystem has a dependency on
in order to supply this: inline std::size_t hash_value(const path& x) { # ifdef BOOST_WINDOWS_API std::size_t seed = 0; for(const path::value_type* it = x.c_str(); *it; ++it) hash_combine(seed, *it == '/' ? L'\\' : *it); return seed; # else // BOOST_POSIX_API return hash_range(x.native().begin(), x.native().end()); # endif } ... Is there any recommended way to avoid the functional dependency?
In this specific case, I would forward-declare hash_combine and hash_range. I already submitted a pull request against array along the same lines, which Marshall graciously accepted. Had 'hash' been in its own module, I would consider simply including hash.hpp, rather than relying on forward declarations, as 'hash' should be a very lightweight module.
Beman Dawes wrote:
Filesystem has a dependency on
in order to supply this: inline std::size_t hash_value(const path& x) { # ifdef BOOST_WINDOWS_API std::size_t seed = 0; for(const path::value_type* it = x.c_str(); *it; ++it) hash_combine(seed, *it == '/' ? L'\\' : *it); return seed; # else // BOOST_POSIX_API return hash_range(x.native().begin(), x.native().end()); # endif } ... Is there any recommended way to avoid the functional dependency?
In this specific case, I would forward-declare hash_combine and hash_range.
There is also the option of just returning hash_value( x.native() ). This would require a forward declaration of hash_value for string.
On 9 January 2015 at 20:30, Peter Dimov
There is also the option of just returning hash_value( x.native() ). This would require a forward declaration of hash_value for string.
I wanted hash_fwd.hpp to depend on minimal standard headers. My preference is to use something like: 'boost::hash<T> hasher; return hasher(x.native())'. Could possibly add a convenience function, maybe 'call_hash'.
Daniel James wrote:
My preference is to use something like: 'boost::hash<T> hasher; return hasher(x.native())'.
That's what I do in shared_ptr, but in path's case, I don't believe that it can be done. hash_value( path ) does not depend on a template parameter, so the definition of hash<string> must be visible (on compilers that implement two-phase lookup properly).
On 9 January 2015 at 22:27, Peter Dimov
Daniel James wrote:
My preference is to use something like: 'boost::hash<T> hasher; return hasher(x.native())'.
That's what I do in shared_ptr, but in path's case, I don't believe that it can be done. hash_value( path ) does not depend on a template parameter, so the definition of hash<string> must be visible (on compilers that implement two-phase lookup properly).
Then it'd probably be better to have forwarding headers for support of
each standard header, e.g.
El 09/01/2015 a las 21:17, Peter Dimov escribió:
Beman Dawes wrote:
Filesystem has a dependency on
in order to supply this: inline std::size_t hash_value(const path& x) { # ifdef BOOST_WINDOWS_API std::size_t seed = 0; for(const path::value_type* it = x.c_str(); *it; ++it) hash_combine(seed, *it == '/' ? L'\\' : *it); return seed; # else // BOOST_POSIX_API return hash_range(x.native().begin(), x.native().end()); # endif } ... Is there any recommended way to avoid the functional dependency?
In this specific case, I would forward-declare hash_combine and hash_range. I already submitted a pull request against array along the same lines, which Marshall graciously accepted.
But shouldn't a function calling hash_combine include the header with the implementation (that is, "hash.hpp")? Or it is assumed that since hash_value will normally be called via ::boost::hash+ADL someone must have included it?
Had 'hash' been in its own module, I would consider simply including hash.hpp, rather than relying on forward declarations, as 'hash' should be a very lightweight module.
Not if it includes implementation for several types, and does now for standard types. including hash.hpp might import a non-negligible amount of headers. In case case, I think putting "hash" in its own module it's a very good idea, maybe with new headers in boost/hash, maintaining backwards compatibility from functional/hash includes. Best, Ion
Ion Gaztañaga wrote:
Had 'hash' been in its own module, I would consider simply including hash.hpp, rather than relying on forward declarations, as 'hash' should be a very lightweight module.
Not if it includes implementation for several types, and does now for standard types. including hash.hpp might import a non-negligible amount of headers.
This is solvable by splitting hash.hpp into hash/core.hpp, hash/map.hpp, hash/vector.hpp, and so on. Ordinary users include hash.hpp, People Who Care only include what's needed. I, personally, don't care that much about the standard headers, because in my experience, translation units often end up including most of the standard library anyway; but I do acknowledge that not everyone feels the same way.
participants (5)
-
Andrzej Krzemienski
-
Beman Dawes
-
Daniel James
-
Ion Gaztañaga
-
Peter Dimov