diff --git a/include/boost/system/error_code.hpp b/include/boost/system/error_code.hpp index 3bce6ef..c92a18e 100644 --- a/include/boost/system/error_code.hpp +++ b/include/boost/system/error_code.hpp @@ -162,8 +162,14 @@ template<> struct is_error_condition_enum #pragma warning( disable: 4355 ) #endif +std::size_t hash_value( error_code const & ec ); + class BOOST_SYMBOL_VISIBLE error_category { +private: + + friend std::size_t hash_value( error_code const & ec ); + #if !defined(BOOST_NO_CXX11_DELETED_FUNCTIONS) public: @@ -692,10 +698,31 @@ template return os; } -inline std::size_t hash_value( const error_code & ec ) +inline std::size_t hash_value( error_code const & ec ) { - // TODO use category id_, FNV combiner - return static_cast( ec.value() ) + reinterpret_cast( &ec.category() ); + error_category const & cat = ec.category(); + + boost::ulong_long_type id = cat.id_; + + if( id == 0 ) + { + id = reinterpret_cast( &cat ); + } + + boost::ulong_long_type hv = 0xCBF29CE484222325ull; + boost::ulong_long_type const prime = 0x00000100000001B3ull; + + // id + + hv ^= id; + hv *= prime; + + // value + + hv ^= static_cast( ec.value() ); + hv *= prime; + + return static_cast( hv ); } // make_* functions for errc::errc_t diff --git a/test/single_instance_test.cpp b/test/single_instance_test.cpp index d5b67cf..65de5a9 100644 --- a/test/single_instance_test.cpp +++ b/test/single_instance_test.cpp @@ -25,8 +25,23 @@ error_code get_generic_code(); int main() { - BOOST_TEST_EQ( lib1::get_system_code(), lib2::get_system_code() ); - BOOST_TEST_EQ( lib1::get_generic_code(), lib2::get_generic_code() ); + { + error_code e1 = lib1::get_system_code(); + error_code e2 = lib2::get_system_code(); + + BOOST_TEST_EQ( e1, e2 ); + + BOOST_TEST_EQ( hash_value( e1 ), hash_value( e2 ) ); + } + + { + error_code e1 = lib1::get_generic_code(); + error_code e2 = lib2::get_generic_code(); + + BOOST_TEST_EQ( e1, e2 ); + + BOOST_TEST_EQ( hash_value( e1 ), hash_value( e2 ) ); + } return boost::report_errors(); }