aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorswarmer <swarmer@yandex-team.com>2023-12-07 22:34:45 +0300
committerswarmer <swarmer@yandex-team.com>2023-12-07 22:57:35 +0300
commitadb1ae56bc6e6cce75f28ffa6ccbb44e12de22c3 (patch)
tree5d9b276987c7a64a171a31eaa4b942d504e180f3
parentab0991343189494d8e93e3eff2af16fc3a3ce561 (diff)
downloadydb-adb1ae56bc6e6cce75f28ffa6ccbb44e12de22c3.tar.gz
[util] Store policy should preserve constructor's is_constructible trait
Without constraints on the types of arguments, it is possible that creating an instance of `Policy<T>{}` leads to a compilation error, although immediately before that, checking `std::is_default_constructible_v<TPolicy<T>>` returned `true` value
-rw-r--r--util/generic/store_policy.h10
-rw-r--r--util/generic/store_policy_ut.cpp31
2 files changed, 34 insertions, 7 deletions
diff --git a/util/generic/store_policy.h b/util/generic/store_policy.h
index 148821c70c..497b13f6c4 100644
--- a/util/generic/store_policy.h
+++ b/util/generic/store_policy.h
@@ -5,11 +5,7 @@
template <class TBase, class TCounter>
struct TWithRefCount: public TBase, public TRefCounted<TWithRefCount<TBase, TCounter>, TCounter> {
- template <typename... Args>
- inline TWithRefCount(Args&&... args)
- : TBase(std::forward<Args>(args)...)
- {
- }
+ using TBase::TBase;
};
template <class T>
@@ -32,7 +28,7 @@ struct TPtrPolicy {
template <class T>
struct TEmbedPolicy {
- template <typename... Args>
+ template <typename... Args, typename = typename std::enable_if<std::is_constructible<T, Args...>::value>::type>
inline TEmbedPolicy(Args&&... args)
: T_(std::forward<Args>(args)...)
{
@@ -53,7 +49,7 @@ template <class T, class TCounter>
struct TRefPolicy {
using THelper = TWithRefCount<T, TCounter>;
- template <typename... Args>
+ template <typename... Args, typename = typename std::enable_if<std::is_constructible<T, Args...>::value>::type>
inline TRefPolicy(Args&&... args)
: T_(new THelper(std::forward<Args>(args)...))
{
diff --git a/util/generic/store_policy_ut.cpp b/util/generic/store_policy_ut.cpp
index e3bdcd61b2..d361338dfa 100644
--- a/util/generic/store_policy_ut.cpp
+++ b/util/generic/store_policy_ut.cpp
@@ -83,4 +83,35 @@ Y_UNIT_TEST_SUITE(StorePolicy) {
UNIT_ASSERT_VALUES_EQUAL(**secondHolder.Ptr(), 42);
});
}
+
+ struct TNoDefaultConstructible {
+ explicit TNoDefaultConstructible(int) noexcept {
+ }
+ };
+
+ template <class TType, class TBaseType>
+ static void TestStoryPolicyConstructors() {
+ if constexpr (std::is_default_constructible_v<TType>) {
+ TType instance{};
+ Y_UNUSED(instance);
+ }
+ UNIT_ASSERT_VALUES_EQUAL(std::is_default_constructible_v<TType>, std::is_default_constructible_v<TBaseType>);
+ if constexpr (std::is_constructible_v<TType, int>) {
+ TType instance{4};
+ Y_UNUSED(instance);
+ }
+ UNIT_ASSERT_VALUES_EQUAL((std::is_constructible_v<TType, int>), (std::is_constructible_v<TBaseType, int>));
+ }
+
+ template <class TBaseType>
+ static void TestWrapperConstructors() {
+ TestStoryPolicyConstructors<TWithRefCount<TBaseType, TAtomicCounter>, TBaseType>();
+ TestStoryPolicyConstructors<TEmbedPolicy<TBaseType>, TBaseType>();
+ TestStoryPolicyConstructors<TSimpleRefPolicy<TBaseType>, TBaseType>();
+ }
+
+ Y_UNIT_TEST(ConstructorTraits) {
+ TestWrapperConstructors<TNoDefaultConstructible>();
+ TestWrapperConstructors<TVector<short>>();
+ }
}