
----- Mensaje original ----- De: Alberto Barbati <abarbati@iaanus.com> Fecha: Viernes, Marzo 11, 2005 9:01 pm Asunto: [boost] Re: [review] hash functions
Hi,
I have a doubt about the proposed implementation of hash_value() for pointers, which is:
template <class T> inline std::size_t hash_value(T* v) { return static_cast<std::size_t>(v - (T*)0); }
this code calls for undefined behaviour according to §5.7/6, each time v is a non-null pointer.
IMHO, the only reasonable way to map generic pointer values to integer values is through reinterpret_cast<>. The mapping would be implementation-defined, but it would be no worse than the intent of the proposed implementation (if it worked).
Agreed.
To be picky, in order to accomodate with implementations that may have sizeof(size_t) < sizeof(T*), we should use two casts:
template <class T> inline std::size_t hash_value(T* v) { return static_cast<std::size_t>( reinterpret_cast<boost::uintmax_t>(v)); }
(the right thing would be to use a C9X-ish uintptr_t type, but boost/cstdint.hpp does not provide such a type).
However, as the double cast may result in suboptimal code if size_t is large enough, a boost::enable_if trick might be used to provide an optimized version with just a single use of reinterpret_cast. The result would be something similar to:
[...] Please, no SFINAE! This would break not-so-conforming compilers. Let's stick to compilerwise macro-based branches. After all, for the vast majority of platforms (AFAIK) sizeof(size_t)==sizeof(T*)
Unfortunately, there's one more thing... even if p == q, reinterpret_cast<uintmax_t>(p) is not guaranteed to be equal to reinterpret_cast<uintmax_t>(q) on implementations that have multiple internal representations for the same address. I don't think much can be done (in a portable way) for such platforms.
Another reason for resorting to macro-based alternatives, and not to SFINAE. Joaquín M López Muñoz Telefónica, Investigación y Desarrollo