//===----------------------------------------------------------------------===// // // 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 TEST_TRANSPARENT_UNORDERED_H #define TEST_TRANSPARENT_UNORDERED_H #include "test_macros.h" #include "is_transparent.h" #include #if TEST_STD_VER > 17 template struct StoredType; template struct SearchedType; struct hash_impl { template constexpr std::size_t operator()(SearchedType const& t) const { return static_cast(t.get_value()); } template constexpr std::size_t operator()(StoredType const& t) const { return static_cast(t.get_value()); } }; struct non_transparent_hash : hash_impl {}; struct transparent_hash : hash_impl { using is_transparent = void; }; struct transparent_hash_final final : transparent_hash {}; struct transparent_equal_final final : std::equal_to<> {}; template struct SearchedType { explicit SearchedType(T value, int *counter) : value_(value), conversions_(counter) { } // Whenever a conversion is performed, increment the counter to keep track // of conversions. operator StoredType() const { ++*conversions_; return StoredType{value_}; } int get_value() const { return value_; } private: T value_; int *conversions_; }; template struct StoredType { StoredType() = default; StoredType(T value) : value_(value) { } friend bool operator==(StoredType const& lhs, StoredType const& rhs) { return lhs.value_ == rhs.value_; } // If we're being passed a SearchedType object, avoid the conversion // to T. This allows testing that the transparent operations are correctly // forwarding the SearchedType all the way to this comparison by checking // that we didn't have a conversion when we search for a SearchedType // in a container full of StoredType. friend bool operator==(StoredType const& lhs, SearchedType const& rhs) { return lhs.value_ == rhs.get_value(); } int get_value() const { return value_; } private: T value_; }; template class UnorderedSet, class Hash, class Equal> using unord_set_type = UnorderedSet, Hash, Equal>; template class UnorderedMap, class Hash, class Equal> using unord_map_type = UnorderedMap, int, Hash, Equal>; template void test_transparent_find(Container c) { int conversions = 0; assert(c.find(SearchedType(1, &conversions)) != c.end()); assert(c.find(SearchedType(2, &conversions)) != c.end()); assert(c.find(SearchedType(3, &conversions)) == c.end()); assert(conversions == 0); } template void test_non_transparent_find(Container c) { int conversions = 0; assert(c.find(SearchedType(1, &conversions)) != c.end()); assert(conversions == 1); assert(c.find(SearchedType(2, &conversions)) != c.end()); assert(conversions == 2); assert(c.find(SearchedType(3, &conversions)) == c.end()); assert(conversions == 3); } template void test_transparent_count(Container c) { int conversions = 0; assert(c.count(SearchedType(1, &conversions)) > 0); assert(c.count(SearchedType(2, &conversions)) > 0); assert(c.count(SearchedType(3, &conversions)) == 0); assert(conversions == 0); } template void test_non_transparent_count(Container c) { int conversions = 0; assert(c.count(SearchedType(1, &conversions)) > 0); assert(conversions == 1); assert(c.count(SearchedType(2, &conversions)) > 0); assert(conversions == 2); assert(c.count(SearchedType(3, &conversions)) == 0); assert(conversions == 3); } template void test_transparent_contains(Container c) { int conversions = 0; assert(c.contains(SearchedType(1, &conversions))); assert(c.contains(SearchedType(2, &conversions))); assert(!c.contains(SearchedType(3, &conversions))); assert(conversions == 0); } template void test_non_transparent_contains(Container c) { int conversions = 0; assert(c.contains(SearchedType(1, &conversions))); assert(conversions == 1); assert(c.contains(SearchedType(2, &conversions))); assert(conversions == 2); assert(!c.contains(SearchedType(3, &conversions))); assert(conversions == 3); } template void test_transparent_equal_range(Container c) { int conversions = 0; auto iters = c.equal_range(SearchedType(1, &conversions)); assert(std::distance(iters.first, iters.second) > 0); iters = c.equal_range(SearchedType(2, &conversions)); assert(std::distance(iters.first, iters.second) > 0); iters = c.equal_range(SearchedType(3, &conversions)); assert(std::distance(iters.first, iters.second) == 0); assert(conversions == 0); } template void test_non_transparent_equal_range(Container c) { int conversions = 0; auto iters = c.equal_range(SearchedType(1, &conversions)); assert(std::distance(iters.first, iters.second) > 0); assert(conversions == 1); iters = c.equal_range(SearchedType(2, &conversions)); assert(std::distance(iters.first, iters.second) > 0); assert(conversions == 2); iters = c.equal_range(SearchedType(3, &conversions)); assert(std::distance(iters.first, iters.second) == 0); assert(conversions == 3); } #endif // TEST_STD_VER > 17 #endif // TEST_TRANSPARENT_UNORDERED_H