diff options
author | swarmer <swarmer@yandex-team.com> | 2023-12-07 22:34:45 +0300 |
---|---|---|
committer | swarmer <swarmer@yandex-team.com> | 2023-12-07 22:57:35 +0300 |
commit | adb1ae56bc6e6cce75f28ffa6ccbb44e12de22c3 (patch) | |
tree | 5d9b276987c7a64a171a31eaa4b942d504e180f3 | |
parent | ab0991343189494d8e93e3eff2af16fc3a3ce561 (diff) | |
download | ydb-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.h | 10 | ||||
-rw-r--r-- | util/generic/store_policy_ut.cpp | 31 |
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>>(); + } } |