Commit 15de336d authored by Adam Ernst's avatar Adam Ernst Committed by Facebook GitHub Bot

@build-break revert D23279680 & D23349316

Summary:
Breaks builds.

overriding_review_checks_triggers_an_audit_and_retroactive_review
Oncall Short Name: fbobjc_sheriff

fbshipit-source-id: 8b6437a9e87e4888a6b7a85637232308412cf416
parent 38e819bc
...@@ -149,10 +149,6 @@ class ConcurrentHashMap { ...@@ -149,10 +149,6 @@ class ConcurrentHashMap {
Atom, Atom,
Mutex, Mutex,
Impl>; Impl>;
template <typename K, typename T>
using EnableHeterogeneousFind = std::enable_if_t<
detail::EligibleForHeterogeneousFind<KeyType, HashFn, KeyEqual, K>::value,
T>;
float load_factor_ = SegmentT::kDefaultLoadFactor; float load_factor_ = SegmentT::kDefaultLoadFactor;
...@@ -169,27 +165,6 @@ class ConcurrentHashMap { ...@@ -169,27 +165,6 @@ class ConcurrentHashMap {
typedef KeyEqual key_equal; typedef KeyEqual key_equal;
typedef ConstIterator const_iterator; typedef ConstIterator const_iterator;
private:
template <typename K, typename T>
using EnableHeterogeneousInsert = std::enable_if_t<
::folly::detail::
EligibleForHeterogeneousInsert<KeyType, HashFn, KeyEqual, K>::value,
T>;
template <typename K>
using IsIter = std::is_same<ConstIterator, remove_cvref_t<K>>;
template <typename K, typename T>
using EnableHeterogeneousErase = std::enable_if_t<
::folly::detail::EligibleForHeterogeneousFind<
KeyType,
HashFn,
KeyEqual,
std::conditional_t<IsIter<K>::value, KeyType, K>>::value &&
!IsIter<K>::value,
T>;
public:
/* /*
* Construct a ConcurrentHashMap with 1 << ShardBits shards, size * Construct a ConcurrentHashMap with 1 << ShardBits shards, size
* and max_size given. Both size and max_size will be rounded up to * and max_size given. Both size and max_size will be rounded up to
...@@ -264,11 +239,14 @@ class ConcurrentHashMap { ...@@ -264,11 +239,14 @@ class ConcurrentHashMap {
return true; return true;
} }
ConstIterator find(const KeyType& k) const { return findImpl(k); } ConstIterator find(const KeyType& k) const {
auto segment = pickSegment(k);
template <typename K, EnableHeterogeneousFind<K, int> = 0> ConstIterator res(this, segment);
ConstIterator find(const K& k) const { auto seg = segments_[segment].load(std::memory_order_acquire);
return findImpl(k); if (!seg || !seg->find(res.it_, k)) {
res.segment_ = NumShards;
}
return res;
} }
ConstIterator cend() const noexcept { return ConstIterator(NumShards); } ConstIterator cend() const noexcept { return ConstIterator(NumShards); }
...@@ -281,12 +259,13 @@ class ConcurrentHashMap { ...@@ -281,12 +259,13 @@ class ConcurrentHashMap {
std::pair<ConstIterator, bool> insert( std::pair<ConstIterator, bool> insert(
std::pair<key_type, mapped_type>&& foo) { std::pair<key_type, mapped_type>&& foo) {
return insertImpl(std::move(foo)); auto segment = pickSegment(foo.first);
} std::pair<ConstIterator, bool> res(
std::piecewise_construct,
template <typename Key, EnableHeterogeneousInsert<Key, int> = 0> std::forward_as_tuple(this, segment),
std::pair<ConstIterator, bool> insert(std::pair<Key, mapped_type>&& foo) { std::forward_as_tuple(false));
return insertImpl(std::move(foo)); res.second = ensureSegment(segment)->insert(res.first.it_, std::move(foo));
return res;
} }
template <typename Key, typename Value> template <typename Key, typename Value>
...@@ -395,26 +374,24 @@ class ConcurrentHashMap { ...@@ -395,26 +374,24 @@ class ConcurrentHashMap {
return item.first->second; return item.first->second;
} }
template <typename Key, EnableHeterogeneousInsert<Key, int> = 0> const ValueType at(const KeyType& key) const {
const ValueType operator[](const Key& key) { auto item = find(key);
auto item = insert(key, ValueType()); if (item == cend()) {
return item.first->second; throw_exception<std::out_of_range>("at(): value out of range");
} }
return item->second;
const ValueType at(const KeyType& key) const { return atImpl(key); }
template <typename K, EnableHeterogeneousFind<K, int> = 0>
const ValueType at(const K& key) const {
return atImpl(key);
} }
// TODO update assign interface, operator[], at // TODO update assign interface, operator[], at
size_type erase(const key_type& k) { return eraseImpl(k); } size_type erase(const key_type& k) {
auto segment = pickSegment(k);
template <typename K, EnableHeterogeneousErase<K, int> = 0> auto seg = segments_[segment].load(std::memory_order_acquire);
size_type erase(const K& k) { if (!seg) {
return eraseImpl(k); return 0;
} else {
return seg->erase(k);
}
} }
// Calls the hash function, and therefore may throw. // Calls the hash function, and therefore may throw.
...@@ -432,24 +409,15 @@ class ConcurrentHashMap { ...@@ -432,24 +409,15 @@ class ConcurrentHashMap {
k, [&expected](const ValueType& v) { return v == expected; }); k, [&expected](const ValueType& v) { return v == expected; });
} }
template <typename K, EnableHeterogeneousErase<K, int> = 0>
size_type erase_if_equal(const K& k, const ValueType& expected) {
return erase_key_if(
k, [&expected](const ValueType& v) { return v == expected; });
}
// Erase if predicate evaluates to true on the existing value // Erase if predicate evaluates to true on the existing value
template <typename Predicate> template <typename Predicate>
size_type erase_key_if(const key_type& k, Predicate&& predicate) { size_type erase_key_if(const key_type& k, Predicate&& predicate) {
return eraseKeyIfImpl(k, std::forward<Predicate>(predicate)); auto segment = pickSegment(k);
} auto seg = segments_[segment].load(std::memory_order_acquire);
if (!seg) {
template < return 0;
typename K, }
typename Predicate, return seg->erase_key_if(k, std::forward<Predicate>(predicate));
EnableHeterogeneousErase<K, int> = 0>
size_type erase_key_if(const K& k, Predicate&& predicate) {
return eraseKeyIfImpl(k, std::forward<Predicate>(predicate));
} }
// NOT noexcept, initializes new shard segments vs. // NOT noexcept, initializes new shard segments vs.
...@@ -573,60 +541,7 @@ class ConcurrentHashMap { ...@@ -573,60 +541,7 @@ class ConcurrentHashMap {
}; };
private: private:
template <typename K> uint64_t pickSegment(const KeyType& k) const {
ConstIterator findImpl(const K& k) const {
auto segment = pickSegment(k);
ConstIterator res(this, segment);
auto seg = segments_[segment].load(std::memory_order_acquire);
if (!seg || !seg->find(res.it_, k)) {
res.segment_ = NumShards;
}
return res;
}
template <typename K>
const ValueType atImpl(const K& k) const {
auto item = find(k);
if (item == cend()) {
throw_exception<std::out_of_range>("at(): key not in map");
}
return item->second;
}
template <typename Key>
std::pair<ConstIterator, bool> insertImpl(std::pair<Key, mapped_type>&& foo) {
auto segment = pickSegment(foo.first);
std::pair<ConstIterator, bool> res(
std::piecewise_construct,
std::forward_as_tuple(this, segment),
std::forward_as_tuple(false));
res.second = ensureSegment(segment)->insert(res.first.it_, std::move(foo));
return res;
}
template <typename K>
size_type eraseImpl(const K& k) {
auto segment = pickSegment(k);
auto seg = segments_[segment].load(std::memory_order_acquire);
if (!seg) {
return 0;
} else {
return seg->erase(k);
}
}
template <typename K, typename Predicate>
size_type eraseKeyIfImpl(const K& k, Predicate&& predicate) {
auto segment = pickSegment(k);
auto seg = segments_[segment].load(std::memory_order_acquire);
if (!seg) {
return 0;
}
return seg->erase_key_if(k, std::forward<Predicate>(predicate));
}
template <typename K>
uint64_t pickSegment(const K& k) const {
auto h = HashFn()(k); auto h = HashFn()(k);
// Use the lowest bits for our shard bits. // Use the lowest bits for our shard bits.
// //
......
...@@ -16,7 +16,6 @@ ...@@ -16,7 +16,6 @@
#pragma once #pragma once
#include <folly/container/HeterogeneousAccess.h>
#include <folly/container/detail/F14Mask.h> #include <folly/container/detail/F14Mask.h>
#include <folly/lang/Exception.h> #include <folly/lang/Exception.h>
#include <folly/lang/Launder.h> #include <folly/lang/Launder.h>
...@@ -254,10 +253,10 @@ class alignas(64) BucketTable { ...@@ -254,10 +253,10 @@ class alignas(64) BucketTable {
bool empty() { return size() == 0; } bool empty() { return size() == 0; }
template <typename MatchFunc, typename K, typename... Args> template <typename MatchFunc, typename... Args>
bool insert( bool insert(
Iterator& it, Iterator& it,
const K& k, const KeyType& k,
InsertType type, InsertType type,
MatchFunc match, MatchFunc match,
hazptr_obj_cohort<Atom>* cohort, hazptr_obj_cohort<Atom>* cohort,
...@@ -266,10 +265,10 @@ class alignas(64) BucketTable { ...@@ -266,10 +265,10 @@ class alignas(64) BucketTable {
it, k, type, match, nullptr, cohort, std::forward<Args>(args)...); it, k, type, match, nullptr, cohort, std::forward<Args>(args)...);
} }
template <typename MatchFunc, typename K, typename... Args> template <typename MatchFunc, typename... Args>
bool insert( bool insert(
Iterator& it, Iterator& it,
const K& k, const KeyType& k,
InsertType type, InsertType type,
MatchFunc match, MatchFunc match,
Node* cur, Node* cur,
...@@ -334,8 +333,7 @@ class alignas(64) BucketTable { ...@@ -334,8 +333,7 @@ class alignas(64) BucketTable {
oldbuckets->retire(concurrenthashmap::HazptrTableDeleter(oldcount)); oldbuckets->retire(concurrenthashmap::HazptrTableDeleter(oldcount));
} }
template <typename K> bool find(Iterator& res, const KeyType& k) {
bool find(Iterator& res, const K& k) {
auto& hazcurr = res.hazptrs_[1]; auto& hazcurr = res.hazptrs_[1];
auto& haznext = res.hazptrs_[2]; auto& haznext = res.hazptrs_[2];
auto h = HashFn()(k); auto h = HashFn()(k);
...@@ -357,8 +355,8 @@ class alignas(64) BucketTable { ...@@ -357,8 +355,8 @@ class alignas(64) BucketTable {
return false; return false;
} }
template <typename K, typename MatchFunc> template <typename MatchFunc>
std::size_t erase(const K& key, Iterator* iter, MatchFunc match) { std::size_t erase(const KeyType& key, Iterator* iter, MatchFunc match) {
Node* node{nullptr}; Node* node{nullptr};
auto h = HashFn()(key); auto h = HashFn()(key);
{ {
...@@ -605,10 +603,10 @@ class alignas(64) BucketTable { ...@@ -605,10 +603,10 @@ class alignas(64) BucketTable {
DCHECK(buckets); DCHECK(buckets);
} }
template <typename MatchFunc, typename K, typename... Args> template <typename MatchFunc, typename... Args>
bool doInsert( bool doInsert(
Iterator& it, Iterator& it,
const K& k, const KeyType& k,
InsertType type, InsertType type,
MatchFunc match, MatchFunc match,
Node* cur, Node* cur,
...@@ -1145,10 +1143,10 @@ class alignas(64) SIMDTable { ...@@ -1145,10 +1143,10 @@ class alignas(64) SIMDTable {
bool empty() { return size() == 0; } bool empty() { return size() == 0; }
template <typename MatchFunc, typename K, typename... Args> template <typename MatchFunc, typename... Args>
bool insert( bool insert(
Iterator& it, Iterator& it,
const K& k, const KeyType& k,
InsertType type, InsertType type,
MatchFunc match, MatchFunc match,
hazptr_obj_cohort<Atom>* cohort, hazptr_obj_cohort<Atom>* cohort,
...@@ -1198,10 +1196,10 @@ class alignas(64) SIMDTable { ...@@ -1198,10 +1196,10 @@ class alignas(64) SIMDTable {
return true; return true;
} }
template <typename MatchFunc, typename K, typename... Args> template <typename MatchFunc, typename... Args>
bool insert( bool insert(
Iterator& it, Iterator& it,
const K& k, const KeyType& k,
InsertType type, InsertType type,
MatchFunc match, MatchFunc match,
Node* cur, Node* cur,
...@@ -1254,8 +1252,7 @@ class alignas(64) SIMDTable { ...@@ -1254,8 +1252,7 @@ class alignas(64) SIMDTable {
rehash_internal(folly::nextPowTwo(new_chunk_count), cohort); rehash_internal(folly::nextPowTwo(new_chunk_count), cohort);
} }
template <typename K> bool find(Iterator& res, const KeyType& k) {
bool find(Iterator& res, const K& k) {
auto& hazz = res.hazptrs_[1]; auto& hazz = res.hazptrs_[1];
auto h = HashFn()(k); auto h = HashFn()(k);
auto hp = splitHash(h); auto hp = splitHash(h);
...@@ -1287,8 +1284,8 @@ class alignas(64) SIMDTable { ...@@ -1287,8 +1284,8 @@ class alignas(64) SIMDTable {
return false; return false;
} }
template <typename K, typename MatchFunc> template <typename MatchFunc>
std::size_t erase(const K& key, Iterator* iter, MatchFunc match) { std::size_t erase(const KeyType& key, Iterator* iter, MatchFunc match) {
auto h = HashFn()(key); auto h = HashFn()(key);
const HashPair hp = splitHash(h); const HashPair hp = splitHash(h);
...@@ -1391,9 +1388,8 @@ class alignas(64) SIMDTable { ...@@ -1391,9 +1388,8 @@ class alignas(64) SIMDTable {
static size_t probeDelta(HashPair hp) { return 2 * hp.second + 1; } static size_t probeDelta(HashPair hp) { return 2 * hp.second + 1; }
// Must hold lock. // Must hold lock.
template <typename K>
Node* find_internal( Node* find_internal(
const K& k, const KeyType& k,
const HashPair& hp, const HashPair& hp,
Chunks* chunks, Chunks* chunks,
size_t ccount, size_t ccount,
...@@ -1422,10 +1418,10 @@ class alignas(64) SIMDTable { ...@@ -1422,10 +1418,10 @@ class alignas(64) SIMDTable {
return nullptr; return nullptr;
} }
template <typename MatchFunc, typename K, typename... Args> template <typename MatchFunc, typename... Args>
bool prepare_insert( bool prepare_insert(
Iterator& it, Iterator& it,
const K& k, const KeyType& k,
InsertType type, InsertType type,
MatchFunc match, MatchFunc match,
hazptr_obj_cohort<Atom>* cohort, hazptr_obj_cohort<Atom>* cohort,
...@@ -1650,8 +1646,7 @@ class alignas(64) ConcurrentHashMapSegment { ...@@ -1650,8 +1646,7 @@ class alignas(64) ConcurrentHashMapSegment {
bool empty() { return impl_.empty(); } bool empty() { return impl_.empty(); }
template <typename Key> bool insert(Iterator& it, std::pair<key_type, mapped_type>&& foo) {
bool insert(Iterator& it, std::pair<Key, mapped_type>&& foo) {
return insert(it, std::move(foo.first), std::move(foo.second)); return insert(it, std::move(foo.first), std::move(foo.second));
} }
...@@ -1751,10 +1746,10 @@ class alignas(64) ConcurrentHashMapSegment { ...@@ -1751,10 +1746,10 @@ class alignas(64) ConcurrentHashMapSegment {
return res; return res;
} }
template <typename MatchFunc, typename K, typename... Args> template <typename MatchFunc, typename... Args>
bool insert_internal( bool insert_internal(
Iterator& it, Iterator& it,
const K& k, const KeyType& k,
InsertType type, InsertType type,
MatchFunc match, MatchFunc match,
Args&&... args) { Args&&... args) {
...@@ -1762,10 +1757,10 @@ class alignas(64) ConcurrentHashMapSegment { ...@@ -1762,10 +1757,10 @@ class alignas(64) ConcurrentHashMapSegment {
it, k, type, match, cohort_, std::forward<Args>(args)...); it, k, type, match, cohort_, std::forward<Args>(args)...);
} }
template <typename MatchFunc, typename K, typename... Args> template <typename MatchFunc, typename... Args>
bool insert_internal( bool insert_internal(
Iterator& it, Iterator& it,
const K& k, const KeyType& k,
InsertType type, InsertType type,
MatchFunc match, MatchFunc match,
Node* cur) { Node* cur) {
...@@ -1775,24 +1770,21 @@ class alignas(64) ConcurrentHashMapSegment { ...@@ -1775,24 +1770,21 @@ class alignas(64) ConcurrentHashMapSegment {
// Must hold lock. // Must hold lock.
void rehash(size_t bucket_count) { impl_.rehash(bucket_count, cohort_); } void rehash(size_t bucket_count) { impl_.rehash(bucket_count, cohort_); }
template <typename K> bool find(Iterator& res, const KeyType& k) { return impl_.find(res, k); }
bool find(Iterator& res, const K& k) {
return impl_.find(res, k);
}
// Listed separately because we need a prev pointer. // Listed separately because we need a prev pointer.
template <typename K> size_type erase(const key_type& key) {
size_type erase(const K& key) {
return erase_internal(key, nullptr, [](const ValueType&) { return true; }); return erase_internal(key, nullptr, [](const ValueType&) { return true; });
} }
template <typename K, typename Predicate> template <typename Predicate>
size_type erase_key_if(const K& key, Predicate&& predicate) { size_type erase_key_if(const key_type& key, Predicate&& predicate) {
return erase_internal(key, nullptr, std::forward<Predicate>(predicate)); return erase_internal(key, nullptr, std::forward<Predicate>(predicate));
} }
template <typename K, typename MatchFunc> template <typename MatchFunc>
size_type erase_internal(const K& key, Iterator* iter, MatchFunc match) { size_type
erase_internal(const key_type& key, Iterator* iter, MatchFunc match) {
return impl_.erase(key, iter, match); return impl_.erase(key, iter, match);
} }
......
...@@ -20,8 +20,6 @@ ...@@ -20,8 +20,6 @@
#include <memory> #include <memory>
#include <thread> #include <thread>
#include <folly/Traits.h>
#include <folly/container/test/TrackingTypes.h>
#include <folly/hash/Hash.h> #include <folly/hash/Hash.h>
#include <folly/portability/GFlags.h> #include <folly/portability/GFlags.h>
#include <folly/portability/GTest.h> #include <folly/portability/GTest.h>
...@@ -832,110 +830,6 @@ TYPED_TEST_P(ConcurrentHashMapTest, IteratorLoop) { ...@@ -832,110 +830,6 @@ TYPED_TEST_P(ConcurrentHashMapTest, IteratorLoop) {
EXPECT_EQ(count, kNum); EXPECT_EQ(count, kNum);
} }
namespace {
template <typename T, typename Arg>
using detector_find = decltype(std::declval<T>().find(std::declval<Arg>()));
template <typename T, typename Arg>
using detector_erase = decltype(std::declval<T>().erase(std::declval<Arg>()));
} // namespace
TYPED_TEST_P(ConcurrentHashMapTest, HeterogeneousLookup) {
using Hasher = folly::transparent<folly::hasher<folly::StringPiece>>;
using KeyEqual = folly::transparent<std::equal_to<folly::StringPiece>>;
using M = ConcurrentHashMap<std::string, bool, Hasher, KeyEqual>;
constexpr auto hello = "hello"_sp;
constexpr auto buddy = "buddy"_sp;
constexpr auto world = "world"_sp;
M map;
map.emplace(hello, true);
map.emplace(world, false);
auto checks = [hello, buddy](auto& ref) {
// find
EXPECT_TRUE(ref.end() == ref.find(buddy));
EXPECT_EQ(hello, ref.find(hello)->first);
// at
EXPECT_TRUE(ref.at(hello));
EXPECT_THROW(ref.at(buddy), std::out_of_range);
// invocability checks
static_assert(
!is_detected_v<detector_find, decltype(ref), int>,
"there shouldn't be a find() overload for this string map with an int param");
};
checks(map);
checks(folly::as_const(map));
}
TYPED_TEST_P(ConcurrentHashMapTest, HeterogeneousInsert) {
using Hasher = folly::transparent<folly::hasher<folly::StringPiece>>;
using KeyEqual = folly::transparent<std::equal_to<folly::StringPiece>>;
using P = std::pair<StringPiece, std::string>;
using CP = std::pair<const StringPiece, std::string>;
ConcurrentHashMap<std::string, std::string, Hasher, KeyEqual> map;
P p{"foo", "hello"};
StringPiece foo{"foo"};
StringPiece bar{"bar"};
map.insert("foo", "hello");
map.insert(foo, "hello");
// TODO(T31574848): the list-initialization below does not work on libstdc++
// versions (e.g., GCC < 6) with no implementation of N4387 ("perfect
// initialization" for pairs and tuples).
// StringPiece sp{"foo"};
// map.insert({sp, "hello"});
map.insert({"foo", "hello"});
map.insert(P("foo", "hello"));
map.insert(CP("foo", "hello"));
map.insert(std::move(p));
map.insert_or_assign("foo", "hello");
map.insert_or_assign(StringPiece{"foo"}, "hello");
map.erase(StringPiece{"foo"});
map.erase(foo);
map.erase("");
EXPECT_TRUE(map.empty());
map.insert("foo", "hello");
map.insert("bar", "world");
map.erase_if_equal(StringPiece{"foo"}, "hello");
map.erase_key_if(bar, [](const std::string& s) { return s == "world"; });
map.erase("");
EXPECT_TRUE(map.empty());
map.insert("foo", "baz");
EXPECT_TRUE(map.assign(foo, "hello2"));
EXPECT_TRUE(map.assign_if_equal("foo", "hello2", "hello"));
EXPECT_EQ(map[foo], "hello");
auto it = map.find(foo);
map.erase(it);
EXPECT_TRUE(map.empty());
map.try_emplace(foo);
map.try_emplace(foo, "hello");
map.try_emplace(StringPiece{"foo"}, "hello");
map.try_emplace(foo, "hello");
map.try_emplace(foo);
map.try_emplace("foo");
map.try_emplace("foo", "hello");
map.try_emplace("bar", /* count */ 20, 'x');
EXPECT_EQ(map[bar], std::string(20, 'x'));
map.emplace(StringPiece{"foo"}, "hello");
map.emplace("foo", "hello");
// invocability checks
static_assert(
!is_detected_v<detector_erase, decltype(map), int>,
"there shouldn't be an erase() overload for this string map with an int param");
}
REGISTER_TYPED_TEST_CASE_P( REGISTER_TYPED_TEST_CASE_P(
ConcurrentHashMapTest, ConcurrentHashMapTest,
MapTest, MapTest,
...@@ -970,9 +864,7 @@ REGISTER_TYPED_TEST_CASE_P( ...@@ -970,9 +864,7 @@ REGISTER_TYPED_TEST_CASE_P(
assignStressTest, assignStressTest,
insertStressTest, insertStressTest,
IteratorMove, IteratorMove,
IteratorLoop, IteratorLoop);
HeterogeneousLookup,
HeterogeneousInsert);
using folly::detail::concurrenthashmap::bucket::BucketTable; using folly::detail::concurrenthashmap::bucket::BucketTable;
......
...@@ -54,7 +54,7 @@ template <typename Policy> ...@@ -54,7 +54,7 @@ template <typename Policy>
class F14BasicMap { class F14BasicMap {
template <typename K, typename T> template <typename K, typename T>
using EnableHeterogeneousFind = std::enable_if_t< using EnableHeterogeneousFind = std::enable_if_t<
::folly::detail::EligibleForHeterogeneousFind< EligibleForHeterogeneousFind<
typename Policy::Key, typename Policy::Key,
typename Policy::Hasher, typename Policy::Hasher,
typename Policy::KeyEqual, typename Policy::KeyEqual,
...@@ -63,7 +63,7 @@ class F14BasicMap { ...@@ -63,7 +63,7 @@ class F14BasicMap {
template <typename K, typename T> template <typename K, typename T>
using EnableHeterogeneousInsert = std::enable_if_t< using EnableHeterogeneousInsert = std::enable_if_t<
::folly::detail::EligibleForHeterogeneousInsert< EligibleForHeterogeneousInsert<
typename Policy::Key, typename Policy::Key,
typename Policy::Hasher, typename Policy::Hasher,
typename Policy::KeyEqual, typename Policy::KeyEqual,
...@@ -77,7 +77,7 @@ class F14BasicMap { ...@@ -77,7 +77,7 @@ class F14BasicMap {
template <typename K, typename T> template <typename K, typename T>
using EnableHeterogeneousErase = std::enable_if_t< using EnableHeterogeneousErase = std::enable_if_t<
::folly::detail::EligibleForHeterogeneousFind< EligibleForHeterogeneousFind<
typename Policy::Key, typename Policy::Key,
typename Policy::Hasher, typename Policy::Hasher,
typename Policy::KeyEqual, typename Policy::KeyEqual,
...@@ -395,7 +395,7 @@ class F14BasicMap { ...@@ -395,7 +395,7 @@ class F14BasicMap {
private: private:
template <typename Arg> template <typename Arg>
using UsableAsKey = ::folly::detail:: using UsableAsKey =
EligibleForHeterogeneousFind<key_type, hasher, key_equal, Arg>; EligibleForHeterogeneousFind<key_type, hasher, key_equal, Arg>;
public: public:
...@@ -953,7 +953,7 @@ class F14VectorMapImpl : public F14BasicMap<MapPolicyWithDefaults< ...@@ -953,7 +953,7 @@ class F14VectorMapImpl : public F14BasicMap<MapPolicyWithDefaults<
template <typename K, typename T> template <typename K, typename T>
using EnableHeterogeneousVectorErase = std::enable_if_t< using EnableHeterogeneousVectorErase = std::enable_if_t<
::folly::detail::EligibleForHeterogeneousFind< EligibleForHeterogeneousFind<
Key, Key,
Hasher, Hasher,
KeyEqual, KeyEqual,
......
...@@ -50,7 +50,7 @@ template <typename Policy> ...@@ -50,7 +50,7 @@ template <typename Policy>
class F14BasicSet { class F14BasicSet {
template <typename K, typename T> template <typename K, typename T>
using EnableHeterogeneousFind = std::enable_if_t< using EnableHeterogeneousFind = std::enable_if_t<
::folly::detail::EligibleForHeterogeneousFind< EligibleForHeterogeneousFind<
typename Policy::Value, typename Policy::Value,
typename Policy::Hasher, typename Policy::Hasher,
typename Policy::KeyEqual, typename Policy::KeyEqual,
...@@ -59,7 +59,7 @@ class F14BasicSet { ...@@ -59,7 +59,7 @@ class F14BasicSet {
template <typename K, typename T> template <typename K, typename T>
using EnableHeterogeneousInsert = std::enable_if_t< using EnableHeterogeneousInsert = std::enable_if_t<
::folly::detail::EligibleForHeterogeneousInsert< EligibleForHeterogeneousInsert<
typename Policy::Value, typename Policy::Value,
typename Policy::Hasher, typename Policy::Hasher,
typename Policy::KeyEqual, typename Policy::KeyEqual,
...@@ -71,7 +71,7 @@ class F14BasicSet { ...@@ -71,7 +71,7 @@ class F14BasicSet {
template <typename K, typename T> template <typename K, typename T>
using EnableHeterogeneousErase = std::enable_if_t< using EnableHeterogeneousErase = std::enable_if_t<
::folly::detail::EligibleForHeterogeneousFind< EligibleForHeterogeneousFind<
typename Policy::Value, typename Policy::Value,
typename Policy::Hasher, typename Policy::Hasher,
typename Policy::KeyEqual, typename Policy::KeyEqual,
...@@ -311,7 +311,7 @@ class F14BasicSet { ...@@ -311,7 +311,7 @@ class F14BasicSet {
private: private:
template <typename Arg> template <typename Arg>
using UsableAsKey = ::folly::detail:: using UsableAsKey =
EligibleForHeterogeneousFind<key_type, hasher, key_equal, Arg>; EligibleForHeterogeneousFind<key_type, hasher, key_equal, Arg>;
public: public:
...@@ -718,7 +718,7 @@ class F14VectorSetImpl : public F14BasicSet<SetPolicyWithDefaults< ...@@ -718,7 +718,7 @@ class F14VectorSetImpl : public F14BasicSet<SetPolicyWithDefaults<
template <typename K, typename T> template <typename K, typename T>
using EnableHeterogeneousVectorErase = std::enable_if_t< using EnableHeterogeneousVectorErase = std::enable_if_t<
::folly::detail::EligibleForHeterogeneousFind< EligibleForHeterogeneousFind<
typename Policy::Value, typename Policy::Value,
typename Policy::Hasher, typename Policy::Hasher,
typename Policy::KeyEqual, typename Policy::KeyEqual,
......
...@@ -143,27 +143,6 @@ struct TransparentRangeHash { ...@@ -143,27 +143,6 @@ struct TransparentRangeHash {
} }
}; };
template <
typename TableKey,
typename Hasher,
typename KeyEqual,
typename ArgKey>
struct EligibleForHeterogeneousFind
: Conjunction<
is_transparent<Hasher>,
is_transparent<KeyEqual>,
is_invocable<Hasher, ArgKey const&>,
is_invocable<KeyEqual, ArgKey const&, TableKey const&>> {};
template <
typename TableKey,
typename Hasher,
typename KeyEqual,
typename ArgKey>
using EligibleForHeterogeneousInsert = Conjunction<
EligibleForHeterogeneousFind<TableKey, Hasher, KeyEqual, ArgKey>,
std::is_constructible<TableKey, ArgKey>>;
} // namespace detail } // namespace detail
template <typename T> template <typename T>
......
...@@ -43,14 +43,12 @@ class F14BasicMap : public std::unordered_map<K, M, H, E, A> { ...@@ -43,14 +43,12 @@ class F14BasicMap : public std::unordered_map<K, M, H, E, A> {
using Super = std::unordered_map<K, M, H, E, A>; using Super = std::unordered_map<K, M, H, E, A>;
template <typename K2, typename T> template <typename K2, typename T>
using EnableHeterogeneousFind = std::enable_if_t< using EnableHeterogeneousFind =
::folly::detail::EligibleForHeterogeneousFind<K, H, E, K2>::value, std::enable_if_t<EligibleForHeterogeneousFind<K, H, E, K2>::value, T>;
T>;
template <typename K2, typename T> template <typename K2, typename T>
using EnableHeterogeneousInsert = std::enable_if_t< using EnableHeterogeneousInsert =
::folly::detail::EligibleForHeterogeneousInsert<K, H, E, K2>::value, std::enable_if_t<EligibleForHeterogeneousInsert<K, H, E, K2>::value, T>;
T>;
template <typename K2> template <typename K2>
using IsIter = Disjunction< using IsIter = Disjunction<
...@@ -59,7 +57,7 @@ class F14BasicMap : public std::unordered_map<K, M, H, E, A> { ...@@ -59,7 +57,7 @@ class F14BasicMap : public std::unordered_map<K, M, H, E, A> {
template <typename K2, typename T> template <typename K2, typename T>
using EnableHeterogeneousErase = std::enable_if_t< using EnableHeterogeneousErase = std::enable_if_t<
::folly::detail::EligibleForHeterogeneousFind< EligibleForHeterogeneousFind<
K, K,
H, H,
E, E,
...@@ -194,7 +192,7 @@ class F14BasicMap : public std::unordered_map<K, M, H, E, A> { ...@@ -194,7 +192,7 @@ class F14BasicMap : public std::unordered_map<K, M, H, E, A> {
private: private:
template <typename Arg> template <typename Arg>
using UsableAsKey = ::folly::detail:: using UsableAsKey =
EligibleForHeterogeneousFind<key_type, hasher, key_equal, Arg>; EligibleForHeterogeneousFind<key_type, hasher, key_equal, Arg>;
public: public:
......
...@@ -54,14 +54,12 @@ class F14BasicSet ...@@ -54,14 +54,12 @@ class F14BasicSet
private: private:
template <typename K, typename T> template <typename K, typename T>
using EnableHeterogeneousFind = std::enable_if_t< using EnableHeterogeneousFind = std::enable_if_t<
::folly::detail:: EligibleForHeterogeneousFind<key_type, hasher, key_equal, K>::value,
EligibleForHeterogeneousFind<key_type, hasher, key_equal, K>::value,
T>; T>;
template <typename K, typename T> template <typename K, typename T>
using EnableHeterogeneousInsert = std::enable_if_t< using EnableHeterogeneousInsert = std::enable_if_t<
::folly::detail:: EligibleForHeterogeneousInsert<key_type, hasher, key_equal, K>::value,
EligibleForHeterogeneousInsert<key_type, hasher, key_equal, K>::value,
T>; T>;
template <typename K> template <typename K>
...@@ -71,7 +69,7 @@ class F14BasicSet ...@@ -71,7 +69,7 @@ class F14BasicSet
template <typename K, typename T> template <typename K, typename T>
using EnableHeterogeneousErase = std::enable_if_t< using EnableHeterogeneousErase = std::enable_if_t<
::folly::detail::EligibleForHeterogeneousFind< EligibleForHeterogeneousFind<
key_type, key_type,
hasher, hasher,
key_equal, key_equal,
...@@ -103,7 +101,7 @@ class F14BasicSet ...@@ -103,7 +101,7 @@ class F14BasicSet
private: private:
template <typename Arg> template <typename Arg>
using UsableAsKey = ::folly::detail:: using UsableAsKey =
EligibleForHeterogeneousFind<key_type, hasher, key_equal, Arg>; EligibleForHeterogeneousFind<key_type, hasher, key_equal, Arg>;
public: public:
......
...@@ -206,6 +206,27 @@ typename Container::size_type erase_if_impl( ...@@ -206,6 +206,27 @@ typename Container::size_type erase_if_impl(
return old_size - c.size(); return old_size - c.size();
} }
template <
typename TableKey,
typename Hasher,
typename KeyEqual,
typename ArgKey>
struct EligibleForHeterogeneousFind
: Conjunction<
is_transparent<Hasher>,
is_transparent<KeyEqual>,
is_invocable<Hasher, ArgKey const&>,
is_invocable<KeyEqual, ArgKey const&, TableKey const&>> {};
template <
typename TableKey,
typename Hasher,
typename KeyEqual,
typename ArgKey>
using EligibleForHeterogeneousInsert = Conjunction<
EligibleForHeterogeneousFind<TableKey, Hasher, KeyEqual, ArgKey>,
std::is_constructible<TableKey, ArgKey>>;
} // namespace detail } // namespace detail
} // namespace f14 } // namespace f14
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment