diff options
| author | Felix Morgner <felix.morgner@gmail.com> | 2020-01-03 13:10:02 +0100 |
|---|---|---|
| committer | Felix Morgner <felix.morgner@gmail.com> | 2020-01-03 13:10:02 +0100 |
| commit | d5970f8ed49a15d19265c71c8618e32a9534eeee (patch) | |
| tree | c03bc611027f32d9639bfb645523e9bd29b68f42 /include | |
| parent | 8551177740f435bd510df6af3fa3d32da39bb526 (diff) | |
| download | newtype-d5970f8ed49a15d19265c71c8618e32a9534eeee.tar.xz newtype-d5970f8ed49a15d19265c71c8618e32a9534eeee.zip | |
new_type: implement support for derivation of Hash
Diffstat (limited to 'include')
| -rw-r--r-- | include/newtype/derivable.hpp | 7 | ||||
| -rw-r--r-- | include/newtype/impl/type_traits_extensions.hpp | 38 | ||||
| -rw-r--r-- | include/newtype/new_type.hpp | 16 |
3 files changed, 61 insertions, 0 deletions
diff --git a/include/newtype/derivable.hpp b/include/newtype/derivable.hpp index 95353eb..38a2375 100644 --- a/include/newtype/derivable.hpp +++ b/include/newtype/derivable.hpp @@ -36,6 +36,13 @@ namespace nt auto constexpr EqBase = derivable<struct eq_base_tag>{}; /** + * @brief A tag to enable derivation of a specialization of std::hash + * + * @since 1.0.0 + */ + auto constexpr Hash = derivable<struct hash_tag>{}; + + /** * @brief A tag to enable derivation of the implicit "conversion to base type" operator * * @note If this tag is not present in the derivation clause of any given nt::new_type, the type instance only supports explicit diff --git a/include/newtype/impl/type_traits_extensions.hpp b/include/newtype/impl/type_traits_extensions.hpp index 10dbc07..d773d40 100644 --- a/include/newtype/impl/type_traits_extensions.hpp +++ b/include/newtype/impl/type_traits_extensions.hpp @@ -1,6 +1,8 @@ #ifndef NEWTYPE_IMPL_TYPE_TRAITS_EXTENSIONS_HPP #define NEWTYPE_IMPL_TYPE_TRAITS_EXTENSIONS_HPP +#include <cstddef> +#include <functional> #include <iosfwd> #include <type_traits> @@ -1011,6 +1013,42 @@ namespace nt::impl } // namespace compound_arithmetic + inline namespace std_support + { + + /** + * @brief A trait to test if a given type is hashable + * + * @tparam T The type to test + * @note This specialization forms the base case for non-hashable T + */ + template<typename T, typename = void> + struct is_hashable : std::false_type + { + }; + + /** + * @brief A trait to test if a given type is hashable + * + * @tparam T The type to test + * @note This specialization forms the case for hashable T + */ + template<typename T> + struct is_hashable<T, std::void_t<decltype(std::declval<std::hash<T> const &>()(std::declval<T const &>()))>> + : std::is_same<std::size_t, decltype(std::declval<std::hash<T> const &>()(std::declval<T const &>()))> + { + }; + + /** + * @brief A variable template to test if a given type is hashable + * + * @tparam T The type to test + */ + template<typename T> + auto constexpr is_hashable_v = is_hashable<T>::value; + + } // namespace std_support + } // namespace nt::impl #endif
\ No newline at end of file diff --git a/include/newtype/new_type.hpp b/include/newtype/new_type.hpp index a59a074..1477c95 100644 --- a/include/newtype/new_type.hpp +++ b/include/newtype/new_type.hpp @@ -6,6 +6,7 @@ #include "newtype/impl/new_type_storage.hpp" #include "newtype/impl/type_traits_extensions.hpp" +#include <functional> #include <istream> #include <ostream> #include <type_traits> @@ -569,4 +570,19 @@ namespace nt } // namespace nt +namespace std +{ + template<typename BaseType, typename TagType, auto DerivationClause> + struct hash<nt::new_type<BaseType, TagType, DerivationClause>> + { + template<typename BaseTypeT = BaseType, auto DerivationClauseV = DerivationClause> + auto constexpr operator()(nt::new_type<BaseType, TagType, DerivationClause> const & object, + std::enable_if_t<DerivationClauseV(nt::Hash) && nt::impl::is_hashable_v<BaseTypeT>> * = nullptr) const + -> std::size_t + { + return std::hash<BaseType>{}(object.decay()); + } + }; +} // namespace std + #endif |
