Hash: Use SFINAE to avoid implicit casts to numbers.

[SVN r78391]
This commit is contained in:
Daniel James
2012-05-08 22:24:46 +00:00
parent 68f0d9bc6b
commit 8bc410f571
3 changed files with 91 additions and 145 deletions

View File

@@ -16,10 +16,6 @@
#include <string>
#include <boost/limits.hpp>
#if defined(BOOST_HASH_NO_IMPLICIT_CASTS)
#include <boost/static_assert.hpp>
#endif
#if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
#include <boost/type_traits/is_pointer.hpp>
#endif
@@ -37,38 +33,63 @@
namespace boost
{
#if defined(BOOST_HASH_NO_IMPLICIT_CASTS)
namespace hash_detail
{
struct enable_hash_value { typedef std::size_t type; };
// If you get a static assertion here, it's because hash_value
// isn't declared for your type.
template <typename T>
std::size_t hash_value(T const&) {
BOOST_STATIC_ASSERT((T*) 0 && false);
return 0;
}
template <typename T> struct basic_numbers {};
template <typename T> struct long_numbers {};
template <typename T> struct ulong_numbers {};
template <typename T> struct float_numbers {};
#endif
std::size_t hash_value(bool);
std::size_t hash_value(char);
std::size_t hash_value(unsigned char);
std::size_t hash_value(signed char);
std::size_t hash_value(short);
std::size_t hash_value(unsigned short);
std::size_t hash_value(int);
std::size_t hash_value(unsigned int);
std::size_t hash_value(long);
std::size_t hash_value(unsigned long);
template <> struct basic_numbers<bool> :
boost::hash_detail::enable_hash_value {};
template <> struct basic_numbers<char> :
boost::hash_detail::enable_hash_value {};
template <> struct basic_numbers<unsigned char> :
boost::hash_detail::enable_hash_value {};
template <> struct basic_numbers<signed char> :
boost::hash_detail::enable_hash_value {};
template <> struct basic_numbers<short> :
boost::hash_detail::enable_hash_value {};
template <> struct basic_numbers<unsigned short> :
boost::hash_detail::enable_hash_value {};
template <> struct basic_numbers<int> :
boost::hash_detail::enable_hash_value {};
template <> struct basic_numbers<unsigned int> :
boost::hash_detail::enable_hash_value {};
template <> struct basic_numbers<long> :
boost::hash_detail::enable_hash_value {};
template <> struct basic_numbers<unsigned long> :
boost::hash_detail::enable_hash_value {};
#if !defined(BOOST_NO_INTRINSIC_WCHAR_T)
std::size_t hash_value(wchar_t);
template <> struct basic_numbers<wchar_t> :
boost::hash_detail::enable_hash_value {};
#endif
#if !defined(BOOST_NO_LONG_LONG)
std::size_t hash_value(boost::long_long_type);
std::size_t hash_value(boost::ulong_long_type);
template <> struct long_numbers<boost::long_long_type> :
boost::hash_detail::enable_hash_value {};
template <> struct ulong_numbers<boost::ulong_long_type> :
boost::hash_detail::enable_hash_value {};
#endif
template <> struct float_numbers<float> :
boost::hash_detail::enable_hash_value {};
template <> struct float_numbers<double> :
boost::hash_detail::enable_hash_value {};
template <> struct float_numbers<long double> :
boost::hash_detail::enable_hash_value {};
}
template <typename T>
typename boost::hash_detail::basic_numbers<T>::type hash_value(T);
template <typename T>
typename boost::hash_detail::long_numbers<T>::type hash_value(T);
template <typename T>
typename boost::hash_detail::ulong_numbers<T>::type hash_value(T);
#if !BOOST_WORKAROUND(__DMC__, <= 0x848)
template <class T> std::size_t hash_value(T* const&);
#else
@@ -83,14 +104,13 @@ namespace boost
std::size_t hash_value(T (&x)[N]);
#endif
std::size_t hash_value(float v);
std::size_t hash_value(double v);
std::size_t hash_value(long double v);
template <class Ch, class A>
std::size_t hash_value(
std::basic_string<Ch, std::BOOST_HASH_CHAR_TRAITS<Ch>, A> const&);
template <typename T>
typename boost::hash_detail::float_numbers<T>::type hash_value(T);
#if !defined(BOOST_NO_0X_HDR_TYPEINDEX)
std::size_t hash_value(std::type_index);
#endif
@@ -141,74 +161,23 @@ namespace boost
}
}
inline std::size_t hash_value(bool v)
template <typename T>
typename boost::hash_detail::basic_numbers<T>::type hash_value(T v)
{
return static_cast<std::size_t>(v);
}
inline std::size_t hash_value(char v)
{
return static_cast<std::size_t>(v);
}
inline std::size_t hash_value(unsigned char v)
{
return static_cast<std::size_t>(v);
}
inline std::size_t hash_value(signed char v)
{
return static_cast<std::size_t>(v);
}
inline std::size_t hash_value(short v)
{
return static_cast<std::size_t>(v);
}
inline std::size_t hash_value(unsigned short v)
{
return static_cast<std::size_t>(v);
}
inline std::size_t hash_value(int v)
{
return static_cast<std::size_t>(v);
}
inline std::size_t hash_value(unsigned int v)
{
return static_cast<std::size_t>(v);
}
inline std::size_t hash_value(long v)
{
return static_cast<std::size_t>(v);
}
inline std::size_t hash_value(unsigned long v)
{
return static_cast<std::size_t>(v);
}
#if !defined(BOOST_NO_INTRINSIC_WCHAR_T)
inline std::size_t hash_value(wchar_t v)
{
return static_cast<std::size_t>(v);
}
#endif
#if !defined(BOOST_NO_LONG_LONG)
inline std::size_t hash_value(boost::long_long_type v)
template <typename T>
typename boost::hash_detail::long_numbers<T>::type hash_value(T v)
{
return hash_detail::hash_value_signed(v);
}
inline std::size_t hash_value(boost::ulong_long_type v)
template <typename T>
typename boost::hash_detail::ulong_numbers<T>::type hash_value(T v)
{
return hash_detail::hash_value_unsigned(v);
}
#endif
// Implementation by Alberto Barbati and Dave Harris.
#if !BOOST_WORKAROUND(__DMC__, <= 0x848)
@@ -324,17 +293,8 @@ namespace boost
return hash_range(v.begin(), v.end());
}
inline std::size_t hash_value(float v)
{
return boost::hash_detail::float_hash_value(v);
}
inline std::size_t hash_value(double v)
{
return boost::hash_detail::float_hash_value(v);
}
inline std::size_t hash_value(long double v)
template <typename T>
typename boost::hash_detail::float_numbers<T>::type hash_value(T v)
{
return boost::hash_detail::float_hash_value(v);
}

View File

@@ -19,51 +19,37 @@ project hash-tests
test-suite functional/hash
:
[ run hash_fwd_test_1.cpp : : : <define>BOOST_HASH_NO_IMPLICIT_CASTS ]
[ run hash_fwd_test_2.cpp : : : <define>BOOST_HASH_NO_IMPLICIT_CASTS ]
[ run hash_number_test.cpp : : : <define>BOOST_HASH_NO_IMPLICIT_CASTS ]
[ run hash_pointer_test.cpp : : : <define>BOOST_HASH_NO_IMPLICIT_CASTS ]
[ run hash_function_pointer_test.cpp : : : <define>BOOST_HASH_NO_IMPLICIT_CASTS ]
[ run hash_float_test.cpp : : : <define>BOOST_HASH_NO_IMPLICIT_CASTS ]
[ run hash_long_double_test.cpp : : : <define>BOOST_HASH_NO_IMPLICIT_CASTS ]
[ run hash_string_test.cpp : : : <define>BOOST_HASH_NO_IMPLICIT_CASTS ]
[ run hash_range_test.cpp : : : <define>BOOST_HASH_NO_IMPLICIT_CASTS ]
[ run hash_custom_test.cpp : : : <define>BOOST_HASH_NO_IMPLICIT_CASTS ]
[ run hash_global_namespace_test.cpp : : : <define>BOOST_HASH_NO_IMPLICIT_CASTS ]
[ run hash_friend_test.cpp : : : <define>BOOST_HASH_NO_IMPLICIT_CASTS ]
[ run hash_built_in_array_test.cpp : : : <define>BOOST_HASH_NO_IMPLICIT_CASTS ]
[ run hash_value_array_test.cpp : : : <define>BOOST_HASH_NO_IMPLICIT_CASTS ]
[ run hash_vector_test.cpp : : : <define>BOOST_HASH_NO_IMPLICIT_CASTS ]
[ run hash_list_test.cpp : : : <define>BOOST_HASH_NO_IMPLICIT_CASTS ]
[ run hash_deque_test.cpp : : : <define>BOOST_HASH_NO_IMPLICIT_CASTS ]
[ run hash_set_test.cpp : : : <define>BOOST_HASH_NO_IMPLICIT_CASTS ]
[ run hash_map_test.cpp : : : <define>BOOST_HASH_NO_IMPLICIT_CASTS ]
[ run hash_complex_test.cpp : : : <define>BOOST_HASH_NO_IMPLICIT_CASTS ]
[ run hash_type_index_test.cpp : : : <define>BOOST_HASH_NO_IMPLICIT_CASTS ]
[ run hash_std_array_test.cpp : : : <define>BOOST_HASH_NO_IMPLICIT_CASTS ]
[ run hash_std_tuple_test.cpp : : : <define>BOOST_HASH_NO_IMPLICIT_CASTS ]
[ run link_test.cpp link_test_2.cpp : : : <define>BOOST_HASH_NO_IMPLICIT_CASTS ]
[ run link_ext_test.cpp link_no_ext_test.cpp : : : <define>BOOST_HASH_NO_IMPLICIT_CASTS ]
[ run extensions_hpp_test.cpp : : : <define>BOOST_HASH_NO_IMPLICIT_CASTS ]
[ compile-fail hash_no_ext_fail_test.cpp : <define>BOOST_HASH_NO_IMPLICIT_CASTS ]
[ compile-fail namespace_fail_test.cpp : <define>BOOST_HASH_NO_IMPLICIT_CASTS ]
[ compile-fail implicit_fail_test.cpp : <define>BOOST_HASH_NO_IMPLICIT_CASTS ]
[ run hash_no_ext_macro_1.cpp : : : <define>BOOST_HASH_NO_IMPLICIT_CASTS ]
[ run hash_no_ext_macro_2.cpp : : : <define>BOOST_HASH_NO_IMPLICIT_CASTS ]
;
test-suite functional/hash_implicit_casts
:
[ run hash_number_test.cpp : : : : implicit_number ]
[ run hash_pointer_test.cpp : : : : implicit_pointer ]
[ run hash_function_pointer_test.cpp : : : : implicit_function_pointer ]
[ run hash_float_test.cpp : : : : implicit_float ]
[ run hash_string_test.cpp : : : : implicit_string ]
[ run hash_range_test.cpp : : : : implicit_range ]
[ run hash_custom_test.cpp : : : : implicit_custom ]
[ run hash_built_in_array_test.cpp : : : : implicit_built_in_array ]
[ run link_test.cpp link_test_2.cpp : : : : implicit_link ]
[ run implicit_fail_test.cpp : : : : implicit_test ]
[ run hash_fwd_test_1.cpp ]
[ run hash_fwd_test_2.cpp ]
[ run hash_number_test.cpp ]
[ run hash_pointer_test.cpp ]
[ run hash_function_pointer_test.cpp ]
[ run hash_float_test.cpp ]
[ run hash_long_double_test.cpp ]
[ run hash_string_test.cpp ]
[ run hash_range_test.cpp ]
[ run hash_custom_test.cpp ]
[ run hash_global_namespace_test.cpp ]
[ run hash_friend_test.cpp ]
[ run hash_built_in_array_test.cpp ]
[ run hash_value_array_test.cpp ]
[ run hash_vector_test.cpp ]
[ run hash_list_test.cpp ]
[ run hash_deque_test.cpp ]
[ run hash_set_test.cpp ]
[ run hash_map_test.cpp ]
[ run hash_complex_test.cpp ]
[ run hash_type_index_test.cpp ]
[ run hash_std_array_test.cpp ]
[ run hash_std_tuple_test.cpp ]
[ run link_test.cpp link_test_2.cpp ]
[ run link_ext_test.cpp link_no_ext_test.cpp ]
[ run extensions_hpp_test.cpp ]
[ compile-fail hash_no_ext_fail_test.cpp ]
[ compile-fail namespace_fail_test.cpp ]
[ run implicit_test.cpp ]
[ run hash_no_ext_macro_1.cpp ]
[ run hash_no_ext_macro_2.cpp ]
;
test-suite functional/hash_no_ext