Commit 6d9ea2b4 by Evan Brown Committed by Copybara-Service

Add common_policy_traits - a subset of hash_policy_traits that can be shared…

Add common_policy_traits - a subset of hash_policy_traits that can be shared between raw_hash_set and btree.

Also remove the transfer implementations from btree_set.h and flat_hash_set.h, which are equivalent to the default implementations.

Motivation: this will simplify upcoming changes related to trivial relocation.
PiperOrigin-RevId: 477493403
Change-Id: I75babef4c93dec3a8105f86c58af54199bb1ec9c
parent df19c209
...@@ -71,6 +71,7 @@ set(ABSL_INTERNAL_DLL_FILES ...@@ -71,6 +71,7 @@ set(ABSL_INTERNAL_DLL_FILES
"container/internal/btree.h" "container/internal/btree.h"
"container/internal/btree_container.h" "container/internal/btree_container.h"
"container/internal/common.h" "container/internal/common.h"
"container/internal/common_policy_traits.h"
"container/internal/compressed_tuple.h" "container/internal/compressed_tuple.h"
"container/internal/container_memory.h" "container/internal/container_memory.h"
"container/internal/counting_allocator.h" "container/internal/counting_allocator.h"
......
...@@ -460,7 +460,10 @@ cc_library( ...@@ -460,7 +460,10 @@ cc_library(
hdrs = ["internal/hash_policy_traits.h"], hdrs = ["internal/hash_policy_traits.h"],
copts = ABSL_DEFAULT_COPTS, copts = ABSL_DEFAULT_COPTS,
linkopts = ABSL_DEFAULT_LINKOPTS, linkopts = ABSL_DEFAULT_LINKOPTS,
deps = ["//absl/meta:type_traits"], deps = [
":common_policy_traits",
"//absl/meta:type_traits",
],
) )
cc_test( cc_test(
...@@ -475,6 +478,26 @@ cc_test( ...@@ -475,6 +478,26 @@ cc_test(
) )
cc_library( cc_library(
name = "common_policy_traits",
hdrs = ["internal/common_policy_traits.h"],
copts = ABSL_DEFAULT_COPTS,
linkopts = ABSL_DEFAULT_LINKOPTS,
visibility = ["//visibility:private"],
deps = ["//absl/meta:type_traits"],
)
cc_test(
name = "common_policy_traits_test",
srcs = ["internal/common_policy_traits_test.cc"],
copts = ABSL_TEST_COPTS,
linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
":common_policy_traits",
"@com_google_googletest//:gtest_main",
],
)
cc_library(
name = "hashtable_debug", name = "hashtable_debug",
hdrs = ["internal/hashtable_debug.h"], hdrs = ["internal/hashtable_debug.h"],
copts = ABSL_DEFAULT_COPTS, copts = ABSL_DEFAULT_COPTS,
...@@ -905,6 +928,7 @@ cc_library( ...@@ -905,6 +928,7 @@ cc_library(
visibility = ["//visibility:public"], visibility = ["//visibility:public"],
deps = [ deps = [
":common", ":common",
":common_policy_traits",
":compressed_tuple", ":compressed_tuple",
":container_memory", ":container_memory",
":layout", ":layout",
......
...@@ -28,6 +28,7 @@ absl_cc_library( ...@@ -28,6 +28,7 @@ absl_cc_library(
${ABSL_DEFAULT_LINKOPTS} ${ABSL_DEFAULT_LINKOPTS}
DEPS DEPS
absl::container_common absl::container_common
absl::common_policy_traits
absl::compare absl::compare
absl::compressed_tuple absl::compressed_tuple
absl::container_memory absl::container_memory
...@@ -531,6 +532,7 @@ absl_cc_library( ...@@ -531,6 +532,7 @@ absl_cc_library(
COPTS COPTS
${ABSL_DEFAULT_COPTS} ${ABSL_DEFAULT_COPTS}
DEPS DEPS
absl::common_policy_traits
absl::meta absl::meta
PUBLIC PUBLIC
) )
...@@ -550,6 +552,31 @@ absl_cc_test( ...@@ -550,6 +552,31 @@ absl_cc_test(
# Internal-only target, do not depend on directly. # Internal-only target, do not depend on directly.
absl_cc_library( absl_cc_library(
NAME NAME
common_policy_traits
HDRS
"internal/common_policy_traits.h"
COPTS
${ABSL_DEFAULT_COPTS}
DEPS
absl::meta
PUBLIC
)
absl_cc_test(
NAME
common_policy_traits_test
SRCS
"internal/common_policy_traits_test.cc"
COPTS
${ABSL_TEST_COPTS}
DEPS
absl::common_policy_traits
GTest::gmock_main
)
# Internal-only target, do not depend on directly.
absl_cc_library(
NAME
hashtablez_sampler hashtablez_sampler
HDRS HDRS
"internal/hashtablez_sampler.h" "internal/hashtablez_sampler.h"
......
...@@ -760,12 +760,6 @@ struct set_slot_policy { ...@@ -760,12 +760,6 @@ struct set_slot_policy {
static void destroy(Alloc *alloc, slot_type *slot) { static void destroy(Alloc *alloc, slot_type *slot) {
absl::allocator_traits<Alloc>::destroy(*alloc, slot); absl::allocator_traits<Alloc>::destroy(*alloc, slot);
} }
template <typename Alloc>
static void transfer(Alloc *alloc, slot_type *new_slot, slot_type *old_slot) {
construct(alloc, new_slot, old_slot);
destroy(alloc, old_slot);
}
}; };
// A parameters structure for holding the type parameters for a btree_set. // A parameters structure for holding the type parameters for a btree_set.
......
...@@ -474,13 +474,6 @@ struct FlatHashSetPolicy { ...@@ -474,13 +474,6 @@ struct FlatHashSetPolicy {
absl::allocator_traits<Allocator>::destroy(*alloc, slot); absl::allocator_traits<Allocator>::destroy(*alloc, slot);
} }
template <class Allocator>
static void transfer(Allocator* alloc, slot_type* new_slot,
slot_type* old_slot) {
construct(alloc, new_slot, std::move(*old_slot));
destroy(alloc, old_slot);
}
static T& element(slot_type* slot) { return *slot; } static T& element(slot_type* slot) { return *slot; }
template <class F, class... Args> template <class F, class... Args>
......
...@@ -61,6 +61,7 @@ ...@@ -61,6 +61,7 @@
#include "absl/base/internal/raw_logging.h" #include "absl/base/internal/raw_logging.h"
#include "absl/base/macros.h" #include "absl/base/macros.h"
#include "absl/container/internal/common.h" #include "absl/container/internal/common.h"
#include "absl/container/internal/common_policy_traits.h"
#include "absl/container/internal/compressed_tuple.h" #include "absl/container/internal/compressed_tuple.h"
#include "absl/container/internal/container_memory.h" #include "absl/container/internal/container_memory.h"
#include "absl/container/internal/layout.h" #include "absl/container/internal/layout.h"
...@@ -356,7 +357,7 @@ class map_value_compare { ...@@ -356,7 +357,7 @@ class map_value_compare {
template <typename Key, typename Compare, typename Alloc, int TargetNodeSize, template <typename Key, typename Compare, typename Alloc, int TargetNodeSize,
bool IsMulti, bool IsMap, typename SlotPolicy> bool IsMulti, bool IsMap, typename SlotPolicy>
struct common_params { struct common_params : common_policy_traits<SlotPolicy> {
using original_key_compare = Compare; using original_key_compare = Compare;
// If Compare is a common comparator for a string-like type, then we adapt it // If Compare is a common comparator for a string-like type, then we adapt it
...@@ -438,28 +439,6 @@ struct common_params { ...@@ -438,28 +439,6 @@ struct common_params {
absl::conditional_t<(kNodeSlotSpace / sizeof(slot_type) > absl::conditional_t<(kNodeSlotSpace / sizeof(slot_type) >
(std::numeric_limits<uint8_t>::max)()), (std::numeric_limits<uint8_t>::max)()),
uint16_t, uint8_t>; // NOLINT uint16_t, uint8_t>; // NOLINT
// The following methods are necessary for passing this struct as PolicyTraits
// for node_handle and/or are used within btree.
static value_type &element(slot_type *slot) {
return slot_policy::element(slot);
}
static const value_type &element(const slot_type *slot) {
return slot_policy::element(slot);
}
template <class... Args>
static void construct(Alloc *alloc, slot_type *slot, Args &&...args) {
slot_policy::construct(alloc, slot, std::forward<Args>(args)...);
}
static void construct(Alloc *alloc, slot_type *slot, slot_type *other) {
slot_policy::construct(alloc, slot, other);
}
static void destroy(Alloc *alloc, slot_type *slot) {
slot_policy::destroy(alloc, slot);
}
static void transfer(Alloc *alloc, slot_type *new_slot, slot_type *old_slot) {
slot_policy::transfer(alloc, new_slot, old_slot);
}
}; };
// An adapter class that converts a lower-bound compare into an upper-bound // An adapter class that converts a lower-bound compare into an upper-bound
......
// Copyright 2022 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef ABSL_CONTAINER_INTERNAL_COMMON_POLICY_TRAITS_H_
#define ABSL_CONTAINER_INTERNAL_COMMON_POLICY_TRAITS_H_
#include <cstddef>
#include <memory>
#include <new>
#include <type_traits>
#include <utility>
#include "absl/meta/type_traits.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace container_internal {
// Defines how slots are initialized/destroyed/moved.
template <class Policy, class = void>
struct common_policy_traits {
// The actual object stored in the container.
using slot_type = typename Policy::slot_type;
// PRECONDITION: `slot` is UNINITIALIZED
// POSTCONDITION: `slot` is INITIALIZED
template <class Alloc, class... Args>
static void construct(Alloc* alloc, slot_type* slot, Args&&... args) {
Policy::construct(alloc, slot, std::forward<Args>(args)...);
}
// PRECONDITION: `slot` is INITIALIZED
// POSTCONDITION: `slot` is UNINITIALIZED
template <class Alloc>
static void destroy(Alloc* alloc, slot_type* slot) {
Policy::destroy(alloc, slot);
}
// Transfers the `old_slot` to `new_slot`. Any memory allocated by the
// allocator inside `old_slot` to `new_slot` can be transferred.
//
// OPTIONAL: defaults to:
//
// clone(new_slot, std::move(*old_slot));
// destroy(old_slot);
//
// PRECONDITION: `new_slot` is UNINITIALIZED and `old_slot` is INITIALIZED
// POSTCONDITION: `new_slot` is INITIALIZED and `old_slot` is
// UNINITIALIZED
template <class Alloc>
static void transfer(Alloc* alloc, slot_type* new_slot, slot_type* old_slot) {
transfer_impl(alloc, new_slot, old_slot, 0);
}
// PRECONDITION: `slot` is INITIALIZED
// POSTCONDITION: `slot` is INITIALIZED
// Note: we use remove_const_t so that the two overloads have different args
// in the case of sets with explicitly const value_types.
template <class P = Policy>
static auto element(absl::remove_const_t<slot_type>* slot)
-> decltype(P::element(slot)) {
return P::element(slot);
}
template <class P = Policy>
static auto element(const slot_type* slot) -> decltype(P::element(slot)) {
return P::element(slot);
}
private:
// Use auto -> decltype as an enabler.
template <class Alloc, class P = Policy>
static auto transfer_impl(Alloc* alloc, slot_type* new_slot,
slot_type* old_slot, int)
-> decltype((void)P::transfer(alloc, new_slot, old_slot)) {
P::transfer(alloc, new_slot, old_slot);
}
template <class Alloc>
static void transfer_impl(Alloc* alloc, slot_type* new_slot,
slot_type* old_slot, char) {
construct(alloc, new_slot, std::move(element(old_slot)));
destroy(alloc, old_slot);
}
};
} // namespace container_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_CONTAINER_INTERNAL_COMMON_POLICY_TRAITS_H_
// Copyright 2022 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "absl/container/internal/common_policy_traits.h"
#include <functional>
#include <memory>
#include <new>
#include "gmock/gmock.h"
#include "gtest/gtest.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace container_internal {
namespace {
using ::testing::MockFunction;
using ::testing::Return;
using ::testing::ReturnRef;
using Slot = int;
struct PolicyWithoutOptionalOps {
using slot_type = Slot;
using key_type = Slot;
using init_type = Slot;
static std::function<void(void*, Slot*, Slot)> construct;
static std::function<void(void*, Slot*)> destroy;
static std::function<Slot&(Slot*)> element;
};
std::function<void(void*, Slot*, Slot)> PolicyWithoutOptionalOps::construct;
std::function<void(void*, Slot*)> PolicyWithoutOptionalOps::destroy;
std::function<Slot&(Slot*)> PolicyWithoutOptionalOps::element;
struct PolicyWithOptionalOps : PolicyWithoutOptionalOps {
static std::function<void(void*, Slot*, Slot*)> transfer;
};
std::function<void(void*, Slot*, Slot*)> PolicyWithOptionalOps::transfer;
struct Test : ::testing::Test {
Test() {
PolicyWithoutOptionalOps::construct = [&](void* a1, Slot* a2, Slot a3) {
construct.Call(a1, a2, std::move(a3));
};
PolicyWithoutOptionalOps::destroy = [&](void* a1, Slot* a2) {
destroy.Call(a1, a2);
};
PolicyWithoutOptionalOps::element = [&](Slot* a1) -> Slot& {
return element.Call(a1);
};
PolicyWithOptionalOps::transfer = [&](void* a1, Slot* a2, Slot* a3) {
return transfer.Call(a1, a2, a3);
};
}
std::allocator<Slot> alloc;
int a = 53;
MockFunction<void(void*, Slot*, Slot)> construct;
MockFunction<void(void*, Slot*)> destroy;
MockFunction<Slot&(Slot*)> element;
MockFunction<void(void*, Slot*, Slot*)> transfer;
};
TEST_F(Test, construct) {
EXPECT_CALL(construct, Call(&alloc, &a, 53));
common_policy_traits<PolicyWithoutOptionalOps>::construct(&alloc, &a, 53);
}
TEST_F(Test, destroy) {
EXPECT_CALL(destroy, Call(&alloc, &a));
common_policy_traits<PolicyWithoutOptionalOps>::destroy(&alloc, &a);
}
TEST_F(Test, element) {
int b = 0;
EXPECT_CALL(element, Call(&a)).WillOnce(ReturnRef(b));
EXPECT_EQ(&b, &common_policy_traits<PolicyWithoutOptionalOps>::element(&a));
}
TEST_F(Test, without_transfer) {
int b = 42;
EXPECT_CALL(element, Call(&b)).WillOnce(::testing::ReturnRef(b));
EXPECT_CALL(construct, Call(&alloc, &a, b));
EXPECT_CALL(destroy, Call(&alloc, &b));
common_policy_traits<PolicyWithoutOptionalOps>::transfer(&alloc, &a, &b);
}
TEST_F(Test, with_transfer) {
int b = 42;
EXPECT_CALL(transfer, Call(&alloc, &a, &b));
common_policy_traits<PolicyWithOptionalOps>::transfer(&alloc, &a, &b);
}
} // namespace
} // namespace container_internal
ABSL_NAMESPACE_END
} // namespace absl
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include <type_traits> #include <type_traits>
#include <utility> #include <utility>
#include "absl/container/internal/common_policy_traits.h"
#include "absl/meta/type_traits.h" #include "absl/meta/type_traits.h"
namespace absl { namespace absl {
...@@ -29,7 +30,7 @@ namespace container_internal { ...@@ -29,7 +30,7 @@ namespace container_internal {
// Defines how slots are initialized/destroyed/moved. // Defines how slots are initialized/destroyed/moved.
template <class Policy, class = void> template <class Policy, class = void>
struct hash_policy_traits { struct hash_policy_traits : common_policy_traits<Policy> {
// The type of the keys stored in the hashtable. // The type of the keys stored in the hashtable.
using key_type = typename Policy::key_type; using key_type = typename Policy::key_type;
...@@ -87,43 +88,6 @@ struct hash_policy_traits { ...@@ -87,43 +88,6 @@ struct hash_policy_traits {
// Defaults to false if not provided by the policy. // Defaults to false if not provided by the policy.
using constant_iterators = ConstantIteratorsImpl<>; using constant_iterators = ConstantIteratorsImpl<>;
// PRECONDITION: `slot` is UNINITIALIZED
// POSTCONDITION: `slot` is INITIALIZED
template <class Alloc, class... Args>
static void construct(Alloc* alloc, slot_type* slot, Args&&... args) {
Policy::construct(alloc, slot, std::forward<Args>(args)...);
}
// PRECONDITION: `slot` is INITIALIZED
// POSTCONDITION: `slot` is UNINITIALIZED
template <class Alloc>
static void destroy(Alloc* alloc, slot_type* slot) {
Policy::destroy(alloc, slot);
}
// Transfers the `old_slot` to `new_slot`. Any memory allocated by the
// allocator inside `old_slot` to `new_slot` can be transferred.
//
// OPTIONAL: defaults to:
//
// clone(new_slot, std::move(*old_slot));
// destroy(old_slot);
//
// PRECONDITION: `new_slot` is UNINITIALIZED and `old_slot` is INITIALIZED
// POSTCONDITION: `new_slot` is INITIALIZED and `old_slot` is
// UNINITIALIZED
template <class Alloc>
static void transfer(Alloc* alloc, slot_type* new_slot, slot_type* old_slot) {
transfer_impl(alloc, new_slot, old_slot, 0);
}
// PRECONDITION: `slot` is INITIALIZED
// POSTCONDITION: `slot` is INITIALIZED
template <class P = Policy>
static auto element(slot_type* slot) -> decltype(P::element(slot)) {
return P::element(slot);
}
// Returns the amount of memory owned by `slot`, exclusive of `sizeof(*slot)`. // Returns the amount of memory owned by `slot`, exclusive of `sizeof(*slot)`.
// //
// If `slot` is nullptr, returns the constant amount of memory owned by any // If `slot` is nullptr, returns the constant amount of memory owned by any
...@@ -174,8 +138,8 @@ struct hash_policy_traits { ...@@ -174,8 +138,8 @@ struct hash_policy_traits {
// Used for node handle manipulation. // Used for node handle manipulation.
template <class P = Policy> template <class P = Policy>
static auto mutable_key(slot_type* slot) static auto mutable_key(slot_type* slot)
-> decltype(P::apply(ReturnKey(), element(slot))) { -> decltype(P::apply(ReturnKey(), hash_policy_traits::element(slot))) {
return P::apply(ReturnKey(), element(slot)); return P::apply(ReturnKey(), hash_policy_traits::element(slot));
} }
// Returns the "value" (as opposed to the "key") portion of the element. Used // Returns the "value" (as opposed to the "key") portion of the element. Used
...@@ -184,21 +148,6 @@ struct hash_policy_traits { ...@@ -184,21 +148,6 @@ struct hash_policy_traits {
static auto value(T* elem) -> decltype(P::value(elem)) { static auto value(T* elem) -> decltype(P::value(elem)) {
return P::value(elem); return P::value(elem);
} }
private:
// Use auto -> decltype as an enabler.
template <class Alloc, class P = Policy>
static auto transfer_impl(Alloc* alloc, slot_type* new_slot,
slot_type* old_slot, int)
-> decltype((void)P::transfer(alloc, new_slot, old_slot)) {
P::transfer(alloc, new_slot, old_slot);
}
template <class Alloc>
static void transfer_impl(Alloc* alloc, slot_type* new_slot,
slot_type* old_slot, char) {
construct(alloc, new_slot, std::move(element(old_slot)));
destroy(alloc, old_slot);
}
}; };
} // namespace container_internal } // namespace container_internal
......
...@@ -38,81 +38,31 @@ struct PolicyWithoutOptionalOps { ...@@ -38,81 +38,31 @@ struct PolicyWithoutOptionalOps {
using key_type = Slot; using key_type = Slot;
using init_type = Slot; using init_type = Slot;
static std::function<void(void*, Slot*, Slot)> construct;
static std::function<void(void*, Slot*)> destroy;
static std::function<Slot&(Slot*)> element; static std::function<Slot&(Slot*)> element;
static int apply(int v) { return apply_impl(v); } static int apply(int v) { return apply_impl(v); }
static std::function<int(int)> apply_impl; static std::function<int(int)> apply_impl;
static std::function<Slot&(Slot*)> value; static std::function<Slot&(Slot*)> value;
}; };
std::function<void(void*, Slot*, Slot)> PolicyWithoutOptionalOps::construct;
std::function<void(void*, Slot*)> PolicyWithoutOptionalOps::destroy;
std::function<Slot&(Slot*)> PolicyWithoutOptionalOps::element;
std::function<int(int)> PolicyWithoutOptionalOps::apply_impl; std::function<int(int)> PolicyWithoutOptionalOps::apply_impl;
std::function<Slot&(Slot*)> PolicyWithoutOptionalOps::value; std::function<Slot&(Slot*)> PolicyWithoutOptionalOps::value;
struct PolicyWithOptionalOps : PolicyWithoutOptionalOps {
static std::function<void(void*, Slot*, Slot*)> transfer;
};
std::function<void(void*, Slot*, Slot*)> PolicyWithOptionalOps::transfer;
struct Test : ::testing::Test { struct Test : ::testing::Test {
Test() { Test() {
PolicyWithoutOptionalOps::construct = [&](void* a1, Slot* a2, Slot a3) {
construct.Call(a1, a2, std::move(a3));
};
PolicyWithoutOptionalOps::destroy = [&](void* a1, Slot* a2) {
destroy.Call(a1, a2);
};
PolicyWithoutOptionalOps::element = [&](Slot* a1) -> Slot& {
return element.Call(a1);
};
PolicyWithoutOptionalOps::apply_impl = [&](int a1) -> int { PolicyWithoutOptionalOps::apply_impl = [&](int a1) -> int {
return apply.Call(a1); return apply.Call(a1);
}; };
PolicyWithoutOptionalOps::value = [&](Slot* a1) -> Slot& { PolicyWithoutOptionalOps::value = [&](Slot* a1) -> Slot& {
return value.Call(a1); return value.Call(a1);
}; };
PolicyWithOptionalOps::transfer = [&](void* a1, Slot* a2, Slot* a3) {
return transfer.Call(a1, a2, a3);
};
} }
std::allocator<int> alloc; std::allocator<int> alloc;
int a = 53; int a = 53;
MockFunction<void(void*, Slot*, Slot)> construct;
MockFunction<void(void*, Slot*)> destroy;
MockFunction<Slot&(Slot*)> element;
MockFunction<int(int)> apply; MockFunction<int(int)> apply;
MockFunction<Slot&(Slot*)> value; MockFunction<Slot&(Slot*)> value;
MockFunction<void(void*, Slot*, Slot*)> transfer;
}; };
TEST_F(Test, construct) {
EXPECT_CALL(construct, Call(&alloc, &a, 53));
hash_policy_traits<PolicyWithoutOptionalOps>::construct(&alloc, &a, 53);
}
TEST_F(Test, destroy) {
EXPECT_CALL(destroy, Call(&alloc, &a));
hash_policy_traits<PolicyWithoutOptionalOps>::destroy(&alloc, &a);
}
TEST_F(Test, element) {
int b = 0;
EXPECT_CALL(element, Call(&a)).WillOnce(ReturnRef(b));
EXPECT_EQ(&b, &hash_policy_traits<PolicyWithoutOptionalOps>::element(&a));
}
TEST_F(Test, apply) { TEST_F(Test, apply) {
EXPECT_CALL(apply, Call(42)).WillOnce(Return(1337)); EXPECT_CALL(apply, Call(42)).WillOnce(Return(1337));
EXPECT_EQ(1337, (hash_policy_traits<PolicyWithoutOptionalOps>::apply(42))); EXPECT_EQ(1337, (hash_policy_traits<PolicyWithoutOptionalOps>::apply(42)));
...@@ -124,20 +74,6 @@ TEST_F(Test, value) { ...@@ -124,20 +74,6 @@ TEST_F(Test, value) {
EXPECT_EQ(&b, &hash_policy_traits<PolicyWithoutOptionalOps>::value(&a)); EXPECT_EQ(&b, &hash_policy_traits<PolicyWithoutOptionalOps>::value(&a));
} }
TEST_F(Test, without_transfer) {
int b = 42;
EXPECT_CALL(element, Call(&b)).WillOnce(::testing::ReturnRef(b));
EXPECT_CALL(construct, Call(&alloc, &a, b));
EXPECT_CALL(destroy, Call(&alloc, &b));
hash_policy_traits<PolicyWithoutOptionalOps>::transfer(&alloc, &a, &b);
}
TEST_F(Test, with_transfer) {
int b = 42;
EXPECT_CALL(transfer, Call(&alloc, &a, &b));
hash_policy_traits<PolicyWithOptionalOps>::transfer(&alloc, &a, &b);
}
} // namespace } // namespace
} // namespace container_internal } // namespace container_internal
ABSL_NAMESPACE_END ABSL_NAMESPACE_END
......
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