188 lines · c
1//===----------------------------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#ifndef TEST_TRANSPARENT_UNORDERED_H10#define TEST_TRANSPARENT_UNORDERED_H11 12#include "test_macros.h"13#include "is_transparent.h"14 15#include <cassert>16 17#if TEST_STD_VER > 1718 19template <typename T>20struct StoredType;21 22template <typename T>23struct SearchedType;24 25struct hash_impl {26 template <typename T>27 constexpr std::size_t operator()(SearchedType<T> const& t) const {28 return static_cast<std::size_t>(t.get_value());29 }30 31 template <typename T>32 constexpr std::size_t operator()(StoredType<T> const& t) const {33 return static_cast<std::size_t>(t.get_value());34 }35};36 37struct non_transparent_hash : hash_impl {};38 39struct transparent_hash : hash_impl {40 using is_transparent = void;41};42 43struct transparent_hash_final final : transparent_hash {};44 45struct transparent_equal_final final : std::equal_to<> {};46 47template <typename T>48struct SearchedType {49 explicit SearchedType(T value, int *counter) : value_(value), conversions_(counter) { }50 51 // Whenever a conversion is performed, increment the counter to keep track52 // of conversions.53 operator StoredType<T>() const {54 ++*conversions_;55 return StoredType<T>{value_};56 }57 58 int get_value() const {59 return value_;60 }61 62private:63 T value_;64 int *conversions_;65};66 67template <typename T>68struct StoredType {69 StoredType() = default;70 StoredType(T value) : value_(value) { }71 72 friend bool operator==(StoredType const& lhs, StoredType const& rhs) {73 return lhs.value_ == rhs.value_;74 }75 76 // If we're being passed a SearchedType<T> object, avoid the conversion77 // to T. This allows testing that the transparent operations are correctly78 // forwarding the SearchedType all the way to this comparison by checking79 // that we didn't have a conversion when we search for a SearchedType<T>80 // in a container full of StoredType<T>.81 friend bool operator==(StoredType const& lhs, SearchedType<T> const& rhs) {82 return lhs.value_ == rhs.get_value();83 }84 85 int get_value() const {86 return value_;87 }88 89private:90 T value_;91};92 93template<template<class...> class UnorderedSet, class Hash, class Equal>94using unord_set_type = UnorderedSet<StoredType<int>, Hash, Equal>;95 96template<template<class...> class UnorderedMap, class Hash, class Equal>97using unord_map_type = UnorderedMap<StoredType<int>, int, Hash, Equal>;98 99template<class Container>100void test_transparent_find(Container c) {101 int conversions = 0;102 assert(c.find(SearchedType<int>(1, &conversions)) != c.end());103 assert(c.find(SearchedType<int>(2, &conversions)) != c.end());104 assert(c.find(SearchedType<int>(3, &conversions)) == c.end());105 assert(conversions == 0);106}107 108template<class Container>109void test_non_transparent_find(Container c) {110 int conversions = 0;111 assert(c.find(SearchedType<int>(1, &conversions)) != c.end());112 assert(conversions == 1);113 assert(c.find(SearchedType<int>(2, &conversions)) != c.end());114 assert(conversions == 2);115 assert(c.find(SearchedType<int>(3, &conversions)) == c.end());116 assert(conversions == 3);117}118 119template<class Container>120void test_transparent_count(Container c) {121 int conversions = 0;122 assert(c.count(SearchedType<int>(1, &conversions)) > 0);123 assert(c.count(SearchedType<int>(2, &conversions)) > 0);124 assert(c.count(SearchedType<int>(3, &conversions)) == 0);125 assert(conversions == 0);126}127 128template<class Container>129void test_non_transparent_count(Container c) {130 int conversions = 0;131 assert(c.count(SearchedType<int>(1, &conversions)) > 0);132 assert(conversions == 1);133 assert(c.count(SearchedType<int>(2, &conversions)) > 0);134 assert(conversions == 2);135 assert(c.count(SearchedType<int>(3, &conversions)) == 0);136 assert(conversions == 3);137}138 139template<class Container>140void test_transparent_contains(Container c) {141 int conversions = 0;142 assert(c.contains(SearchedType<int>(1, &conversions)));143 assert(c.contains(SearchedType<int>(2, &conversions)));144 assert(!c.contains(SearchedType<int>(3, &conversions)));145 assert(conversions == 0);146}147 148template<class Container>149void test_non_transparent_contains(Container c) {150 int conversions = 0;151 assert(c.contains(SearchedType<int>(1, &conversions)));152 assert(conversions == 1);153 assert(c.contains(SearchedType<int>(2, &conversions)));154 assert(conversions == 2);155 assert(!c.contains(SearchedType<int>(3, &conversions)));156 assert(conversions == 3);157}158 159template<class Container>160void test_transparent_equal_range(Container c) {161 int conversions = 0;162 auto iters = c.equal_range(SearchedType<int>(1, &conversions));163 assert(std::distance(iters.first, iters.second) > 0);164 iters = c.equal_range(SearchedType<int>(2, &conversions));165 assert(std::distance(iters.first, iters.second) > 0);166 iters = c.equal_range(SearchedType<int>(3, &conversions));167 assert(std::distance(iters.first, iters.second) == 0);168 assert(conversions == 0);169}170 171template<class Container>172void test_non_transparent_equal_range(Container c) {173 int conversions = 0;174 auto iters = c.equal_range(SearchedType<int>(1, &conversions));175 assert(std::distance(iters.first, iters.second) > 0);176 assert(conversions == 1);177 iters = c.equal_range(SearchedType<int>(2, &conversions));178 assert(std::distance(iters.first, iters.second) > 0);179 assert(conversions == 2);180 iters = c.equal_range(SearchedType<int>(3, &conversions));181 assert(std::distance(iters.first, iters.second) == 0);182 assert(conversions == 3);183}184 185#endif // TEST_STD_VER > 17186 187#endif // TEST_TRANSPARENT_UNORDERED_H188