Boost logo

Boost :

From: Alberto Barbati (abarbati_at_[hidden])
Date: 2005-03-11 15:01:55


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).

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:

#include <boost/utility.hpp>
#include <boost/cstdint.hpp>

namespace detail
{
   template <class T>
   struct fits_in_size_t
   {
     static const bool value = sizeof(T) <= sizeof(size_t);
   };
}

template <class T>
inline typename boost::enable_if<
   detail::fits_in_size_t<T*>, std::size_t>::type
hash_value(T* v)
{
   return reinterpret_cast<std::size_t>(v);
}

template <class T>
inline typename boost::disable_if<
   detail::fits_in_size_t<T*>, std::size_t>::type
hash_value(T* v)
{
   return static_cast<std::size_t>(
     reinterpret_cast<boost::uintmax_t>(v));
}

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.

HTH,

Alberto


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk