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 65bade2cb2
commit f54e6e8af1
3 changed files with 91 additions and 145 deletions

View File

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

View File

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