std::optional support

This commit is contained in:
Daniel James
2018-01-21 18:38:35 +00:00
parent b9ae7e7fb6
commit ddc05d17df
3 changed files with 105 additions and 0 deletions

View File

@@ -230,6 +230,11 @@ namespace boost
template <typename T> template <typename T>
typename boost::hash_detail::float_numbers<T>::type hash_value(T); typename boost::hash_detail::float_numbers<T>::type hash_value(T);
#if BOOST_HASH_HAS_OPTIONAL
template <typename T>
std::size_t hash_value(std::optional<T> const&);
#endif
#if !defined(BOOST_NO_CXX11_HDR_TYPEINDEX) #if !defined(BOOST_NO_CXX11_HDR_TYPEINDEX)
std::size_t hash_value(std::type_index); std::size_t hash_value(std::type_index);
#endif #endif
@@ -481,6 +486,19 @@ namespace boost
return boost::hash_detail::float_hash_value(v); return boost::hash_detail::float_hash_value(v);
} }
#if BOOST_HASH_HAS_OPTIONAL
template <typename T>
inline std::size_t hash_value(std::optional<T> const& v) {
if (!v) {
// Arbitray value for empty optional.
return 0x12345678;
} else {
boost::hash<T> hf;
return hf(*v);
}
}
#endif
#if !defined(BOOST_NO_CXX11_HDR_TYPEINDEX) #if !defined(BOOST_NO_CXX11_HDR_TYPEINDEX)
inline std::size_t hash_value(std::type_index v) inline std::size_t hash_value(std::type_index v)
{ {
@@ -540,6 +558,16 @@ namespace boost
} \ } \
}; };
#define BOOST_HASH_SPECIALIZE_TEMPLATE_REF(type) \
struct hash<type> \
: public boost::hash_detail::hash_base<type> \
{ \
std::size_t operator()(type const& v) const \
{ \
return boost::hash_value(v); \
} \
};
BOOST_HASH_SPECIALIZE(bool) BOOST_HASH_SPECIALIZE(bool)
BOOST_HASH_SPECIALIZE(char) BOOST_HASH_SPECIALIZE(char)
BOOST_HASH_SPECIALIZE(signed char) BOOST_HASH_SPECIALIZE(signed char)
@@ -598,12 +626,18 @@ namespace boost
BOOST_HASH_SPECIALIZE(boost::uint128_type) BOOST_HASH_SPECIALIZE(boost::uint128_type)
#endif #endif
#if BOOST_HASH_HAS_OPTIONAL
template <typename T>
BOOST_HASH_SPECIALIZE_TEMPLATE_REF(std::optional<T>)
#endif
#if !defined(BOOST_NO_CXX11_HDR_TYPEINDEX) #if !defined(BOOST_NO_CXX11_HDR_TYPEINDEX)
BOOST_HASH_SPECIALIZE(std::type_index) BOOST_HASH_SPECIALIZE(std::type_index)
#endif #endif
#undef BOOST_HASH_SPECIALIZE #undef BOOST_HASH_SPECIALIZE
#undef BOOST_HASH_SPECIALIZE_REF #undef BOOST_HASH_SPECIALIZE_REF
#undef BOOST_HASH_SPECIALIZE_TEMPLATE_REF
// Specializing boost::hash for pointers. // Specializing boost::hash for pointers.

View File

@@ -43,6 +43,7 @@ test-suite container_hash/hash
[ run hash_set_test.cpp ] [ run hash_set_test.cpp ]
[ run hash_map_test.cpp ] [ run hash_map_test.cpp ]
[ run hash_complex_test.cpp ] [ run hash_complex_test.cpp ]
[ run hash_optional_test.cpp ]
[ run hash_type_index_test.cpp ] [ run hash_type_index_test.cpp ]
[ run hash_system_error_test.cpp ] [ run hash_system_error_test.cpp ]
[ run hash_std_array_test.cpp ] [ run hash_std_array_test.cpp ]

View File

@@ -0,0 +1,70 @@
// Copyright 2018 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)
#include "./config.hpp"
#ifndef BOOST_HASH_TEST_STD_INCLUDES
# include <boost/container_hash/hash.hpp>
#endif
#include <boost/config.hpp>
#include <boost/core/lightweight_test.hpp>
#if BOOST_HASH_HAS_OPTIONAL
#include <optional>
#include <string>
void test_optional_int()
{
std::optional<int> x1a;
std::optional<int> x1b;
std::optional<int> x2a(10);
std::optional<int> x2b(x2a);
std::optional<int> x3(20);
boost::hash<std::optional<int> > hasher;
BOOST_TEST(hasher(x1a) == hasher(x1a));
BOOST_TEST(hasher(x1a) == hasher(x1b));
BOOST_TEST(hasher(x1a) != hasher(x2a));
BOOST_TEST(hasher(x1a) != hasher(x3));
BOOST_TEST(hasher(x2a) == hasher(x2a));
BOOST_TEST(hasher(x2b) == hasher(x2b));
BOOST_TEST(hasher(x2a) != hasher(x3));
BOOST_TEST(hasher(x3) == hasher(x3));
}
void test_optional_string()
{
std::optional<std::string> x1a;
std::optional<std::string> x1b;
std::optional<std::string> x2a("10");
std::optional<std::string> x2b(x2a);
std::optional<std::string> x3("20");
boost::hash<std::optional<std::string> > hasher;
BOOST_TEST(hasher(x1a) == hasher(x1a));
BOOST_TEST(hasher(x1a) == hasher(x1b));
BOOST_TEST(hasher(x1a) != hasher(x2a));
BOOST_TEST(hasher(x1a) != hasher(x3));
BOOST_TEST(hasher(x2a) == hasher(x2a));
BOOST_TEST(hasher(x2b) == hasher(x2b));
BOOST_TEST(hasher(x2a) != hasher(x3));
BOOST_TEST(hasher(x3) == hasher(x3));
}
#endif
int main()
{
#if BOOST_HASH_HAS_OPTIONAL
test_optional_int();
test_optional_string();
#else
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "<optional> not available." << std::endl;
#endif
return boost::report_errors();
}