// -*- C++ -*- //===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #ifndef SUPPORT_POISONED_HASH_HELPER_H #define SUPPORT_POISONED_HASH_HELPER_H #include #include #include #include #include #include "test_macros.h" #include "type_algorithms.h" template ()(std::declval()))> constexpr bool can_hash_impl(int) { return std::is_same::value; } template constexpr bool can_hash_impl(long) { return false; } template constexpr bool can_hash() { return can_hash_impl(0); } template struct ConvertibleToSimple { operator To() const { return To{}; } }; template struct ConvertibleTo { To to{}; operator To&() & { return to; } operator To const&() const& { return to; } operator To&&() && { return std::move(to); } operator To const&&() const&& { return std::move(to); } }; // Test that the specified Hash meets the requirements of an enabled hash template > TEST_CONSTEXPR_CXX20 void test_hash_enabled(Key const& key = Key{}) { static_assert(std::is_destructible::value, ""); // Enabled hash requirements static_assert(std::is_default_constructible::value, ""); static_assert(std::is_copy_constructible::value, ""); static_assert(std::is_move_constructible::value, ""); static_assert(std::is_copy_assignable::value, ""); static_assert(std::is_move_assignable::value, ""); #if TEST_STD_VER > 14 static_assert(std::is_swappable::value, ""); #elif defined(_LIBCPP_VERSION) static_assert(std::__is_swappable_v, ""); #endif // Hashable requirements static_assert(can_hash(), ""); static_assert(can_hash(), ""); static_assert(can_hash(), ""); static_assert(can_hash(), ""); static_assert(can_hash(), ""); static_assert(can_hash(), ""); static_assert(can_hash&>(), ""); static_assert(can_hash const&>(), ""); static_assert(can_hash&&>(), ""); static_assert(can_hash&>(), ""); static_assert(can_hash const&>(), ""); static_assert(can_hash&&>(), ""); static_assert(can_hash const&&>(), ""); const Hash h{}; assert(h(key) == h(key)); } // Test that the specified Hash meets the requirements of a disabled hash. template > void test_hash_disabled() { // Disabled hash requirements static_assert(!std::is_default_constructible::value, ""); static_assert(!std::is_copy_constructible::value, ""); static_assert(!std::is_move_constructible::value, ""); static_assert(!std::is_copy_assignable::value, ""); static_assert(!std::is_move_assignable::value, ""); static_assert( !std::is_function::type>::type>::value, ""); // Hashable requirements static_assert(!can_hash(), ""); static_assert(!can_hash(), ""); static_assert(!can_hash(), ""); static_assert(!can_hash(), ""); static_assert(!can_hash(), ""); static_assert(!can_hash(), ""); static_assert(!can_hash&>(), ""); static_assert(!can_hash const&>(), ""); static_assert(!can_hash&&>(), ""); static_assert(!can_hash&>(), ""); static_assert(!can_hash const&>(), ""); static_assert(!can_hash&&>(), ""); static_assert(!can_hash const&&>(), ""); } enum Enum {}; enum EnumClass : bool {}; struct Class {}; // Each header that declares the std::hash template provides enabled // specializations of std::hash for std::nullptr_t and all cv-unqualified // arithmetic, enumeration, and pointer types. #if TEST_STD_VER >= 17 using MaybeNullptr = types::type_list; #else using MaybeNullptr = types::type_list<>; #endif using LibraryHashTypes = types:: concatenate_t, MaybeNullptr>; struct TestHashEnabled { template void operator()() const { test_hash_enabled(); } }; // Test that each of the library hash specializations for arithmetic types, // enum types, and pointer types are available and enabled. template void test_library_hash_specializations_available() { types::for_each(Types(), TestHashEnabled()); } #endif // SUPPORT_POISONED_HASH_HELPER_H