123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293 |
- [/ Copyright 2005-2008 Daniel James.
- / Distributed under the Boost Software License, Version 1.0. (See accompanying
- / file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) ]
- [section:portability Portability]
- [def __boost_hash__ [classref boost::hash]]
- __boost_hash__ is written to be as portable as possible, but unfortunately, several
- older compilers don't support argument dependent lookup (ADL) - the mechanism
- used for customisation. On those compilers custom overloads for `hash_value`
- needs to be declared in the boost namespace.
- On a strictly standards compliant compiler, an overload defined in the
- boost namespace won't be found when __boost_hash__ is instantiated,
- so for these compilers the overload should only be declared in the same
- namespace as the class.
- Let's say we have a simple custom type:
- namespace foo
- {
- template <class T>
- class custom_type
- {
- T value;
- public:
- custom_type(T x) : value(x) {}
- friend std::size_t hash_value(custom_type x)
- {
- __boost_hash__<int> hasher;
- return hasher(x.value);
- }
- };
- }
- On a compliant compiler, when `hash_value` is called for this type,
- it will look at the namespace inside the type and find `hash_value`
- but on a compiler which doesn't support ADL `hash_value` won't be found.
- To make things worse, some compilers which do support ADL won't find
- a friend class defined inside the class.
- So first move the member function out of the class:
- namespace foo
- {
- template <class T>
- class custom_type
- {
- T value;
- public:
- custom_type(T x) : value(x) {}
- std::size_t hash(custom_type x)
- {
- __boost_hash__<T> hasher;
- return hasher(value);
- }
- };
- template <class T>
- inline std::size_t hash_value(custom_type<T> x)
- {
- return x.hash();
- }
- }
- Unfortunately, I couldn't declare hash_value as a friend, as some compilers
- don't support template friends, so instead I declared a member function to
- calculate the hash, and called it from hash_value.
- For compilers which don't support ADL, hash_value needs to be defined in the
- boost namespace:
- #ifdef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP
- namespace boost
- #else
- namespace foo
- #endif
- {
- template <class T>
- std::size_t hash_value(foo::custom_type<T> x)
- {
- return x.hash();
- }
- }
- Full code for this example is at
- [@boost:/libs/container_hash/examples/portable.cpp /libs/container_hash/examples/portable.cpp].
- [endsect]
|