diff options
author | Håvard Pettersen <havardpe@yahooinc.com> | 2022-09-21 09:43:28 +0000 |
---|---|---|
committer | Håvard Pettersen <havardpe@yahooinc.com> | 2022-09-21 11:47:13 +0000 |
commit | 95e8f34f7ee1e7df1db7ef52a189245289d51598 (patch) | |
tree | 20297f587675316621a4dd943f75923ad85de6cd /vespalib | |
parent | 04b195343586990e6a612d33e98c7fa8603ee0f4 (diff) |
use more concepts
Diffstat (limited to 'vespalib')
-rw-r--r-- | vespalib/src/tests/datastore/array_store/array_store_test.cpp | 4 | ||||
-rw-r--r-- | vespalib/src/tests/datastore/unique_store/unique_store_test.cpp | 4 | ||||
-rw-r--r-- | vespalib/src/tests/stash/stash.cpp | 4 | ||||
-rw-r--r-- | vespalib/src/tests/traits/traits_test.cpp | 27 | ||||
-rw-r--r-- | vespalib/src/vespa/vespalib/stllike/hashtable.h | 2 | ||||
-rw-r--r-- | vespalib/src/vespa/vespalib/util/arrayqueue.hpp | 5 | ||||
-rw-r--r-- | vespalib/src/vespa/vespalib/util/small_vector.h | 2 | ||||
-rw-r--r-- | vespalib/src/vespa/vespalib/util/stash.h | 14 | ||||
-rw-r--r-- | vespalib/src/vespa/vespalib/util/traits.h | 30 | ||||
-rw-r--r-- | vespalib/src/vespa/vespalib/util/typify.h | 2 |
10 files changed, 40 insertions, 54 deletions
diff --git a/vespalib/src/tests/datastore/array_store/array_store_test.cpp b/vespalib/src/tests/datastore/array_store/array_store_test.cpp index 9478ef93327..e9dd5860ece 100644 --- a/vespalib/src/tests/datastore/array_store/array_store_test.cpp +++ b/vespalib/src/tests/datastore/array_store/array_store_test.cpp @@ -158,8 +158,8 @@ using ByteFixture = Fixture<uint8_t>; TEST("require that we test with trivial and non-trivial types") { - EXPECT_TRUE(vespalib::can_skip_destruction<NumberFixture::value_type>::value); - EXPECT_FALSE(vespalib::can_skip_destruction<StringFixture::value_type>::value); + EXPECT_TRUE(vespalib::can_skip_destruction<NumberFixture::value_type>); + EXPECT_FALSE(vespalib::can_skip_destruction<StringFixture::value_type>); } TEST_F("control static sizes", NumberFixture(3)) { diff --git a/vespalib/src/tests/datastore/unique_store/unique_store_test.cpp b/vespalib/src/tests/datastore/unique_store/unique_store_test.cpp index 17e7a4bb7ea..92bd5502406 100644 --- a/vespalib/src/tests/datastore/unique_store/unique_store_test.cpp +++ b/vespalib/src/tests/datastore/unique_store/unique_store_test.cpp @@ -304,8 +304,8 @@ using SmallOffsetNumberTest = TestBase<BTreeSmallOffsetNumberUniqueStore>; TEST(UniqueStoreTest, trivial_and_non_trivial_types_are_tested) { - EXPECT_TRUE(vespalib::can_skip_destruction<NumberTest::ValueType>::value); - EXPECT_FALSE(vespalib::can_skip_destruction<StringTest::ValueType>::value); + EXPECT_TRUE(vespalib::can_skip_destruction<NumberTest::ValueType>); + EXPECT_FALSE(vespalib::can_skip_destruction<StringTest::ValueType>); } TYPED_TEST(TestBase, can_add_and_get_values) diff --git a/vespalib/src/tests/stash/stash.cpp b/vespalib/src/tests/stash/stash.cpp index f59cd4c4838..e8f49528d65 100644 --- a/vespalib/src/tests/stash/stash.cpp +++ b/vespalib/src/tests/stash/stash.cpp @@ -221,8 +221,8 @@ TEST("require that constructor parameters are passed correctly") { TEST("require that trivially destructable objects are detected") { Stash stash; - EXPECT_TRUE(can_skip_destruction<Pair>::value); - EXPECT_FALSE(can_skip_destruction<PairD>::value); + EXPECT_TRUE(can_skip_destruction<Pair>); + EXPECT_FALSE(can_skip_destruction<PairD>); stash.create<Pair>(); EXPECT_EQUAL(sum({chunk_header_size(), sizeof(Pair)}), stash.count_used()); stash.create<PairD>(); diff --git a/vespalib/src/tests/traits/traits_test.cpp b/vespalib/src/tests/traits/traits_test.cpp index c898f3b1892..896cec59666 100644 --- a/vespalib/src/tests/traits/traits_test.cpp +++ b/vespalib/src/tests/traits/traits_test.cpp @@ -2,6 +2,7 @@ #include <vespa/vespalib/testkit/test_kit.h> #include <vespa/vespalib/util/traits.h> #include <vespa/vespalib/util/arrayqueue.hpp> +#include <concepts> using namespace vespalib; @@ -27,19 +28,19 @@ struct Child2 : Base { VESPA_CAN_SKIP_DESTRUCTION(Child2); -TEST("require that is_copyable works") { - EXPECT_EQUAL(is_copyable<Simple>::value, true); - EXPECT_EQUAL(is_copyable<Hard>::value, false); - EXPECT_EQUAL(is_copyable<ArrayQueue<Simple> >::value, true); - EXPECT_EQUAL(is_copyable<ArrayQueue<Hard> >::value, false); - EXPECT_EQUAL(is_copyable<std::unique_ptr<Hard> >::value, false); +TEST("require that copy ctor detection works") { + EXPECT_EQUAL(std::copy_constructible<Simple>, true); + EXPECT_EQUAL(std::copy_constructible<Hard>, false); + EXPECT_EQUAL(std::copy_constructible<ArrayQueue<Simple> >, true); + EXPECT_EQUAL(std::copy_constructible<ArrayQueue<Hard> >, false); + EXPECT_EQUAL(std::copy_constructible<std::unique_ptr<Hard> >, false); } TEST("require that can_skip_destruction works") { - EXPECT_EQUAL(can_skip_destruction<Simple>::value, true); - EXPECT_EQUAL(can_skip_destruction<Hard>::value, false); - EXPECT_EQUAL(can_skip_destruction<Child1>::value, false); - EXPECT_EQUAL(can_skip_destruction<Child2>::value, true); + EXPECT_EQUAL(can_skip_destruction<Simple>, true); + EXPECT_EQUAL(can_skip_destruction<Hard>, false); + EXPECT_EQUAL(can_skip_destruction<Child1>, false); + EXPECT_EQUAL(can_skip_destruction<Child2>, true); } struct NoType {}; @@ -47,9 +48,9 @@ struct TypeType { using type = NoType; }; struct NoTypeType { static constexpr int type = 3; }; TEST("require that type type member can be detected") { - EXPECT_FALSE(has_type_type_v<NoType>); - EXPECT_TRUE(has_type_type_v<TypeType>); - EXPECT_FALSE(has_type_type_v<NoTypeType>); + EXPECT_FALSE(has_type_type<NoType>); + EXPECT_TRUE(has_type_type<TypeType>); + EXPECT_FALSE(has_type_type<NoTypeType>); } TEST_MAIN() { TEST_RUN_ALL(); } diff --git a/vespalib/src/vespa/vespalib/stllike/hashtable.h b/vespalib/src/vespa/vespalib/stllike/hashtable.h index c064690296f..0be9442ad54 100644 --- a/vespalib/src/vespa/vespalib/stllike/hashtable.h +++ b/vespalib/src/vespa/vespalib/stllike/hashtable.h @@ -170,7 +170,7 @@ public: bool hasNext() const noexcept { return valid() && (_next != npos); } private: void destruct() noexcept { - if constexpr (!can_skip_destruction<V>::value) { + if constexpr (!can_skip_destruction<V>) { if (valid()) { getValue().~V(); } diff --git a/vespalib/src/vespa/vespalib/util/arrayqueue.hpp b/vespalib/src/vespa/vespalib/util/arrayqueue.hpp index 8f3dd8ab006..a44c514e847 100644 --- a/vespalib/src/vespa/vespalib/util/arrayqueue.hpp +++ b/vespalib/src/vespa/vespalib/util/arrayqueue.hpp @@ -2,11 +2,11 @@ #pragma once -#include "traits.h" #include <cstdint> #include <cstdlib> #include <cassert> #include <algorithm> +#include <concepts> namespace vespalib { @@ -119,8 +119,7 @@ public: * * @param q the queue that should be copied **/ - ArrayQueue(typename std::conditional<is_copyable<T>::value, void_tag, const ArrayQueue &>::type q) = delete; - ArrayQueue(typename std::conditional<is_copyable<T>::value, const ArrayQueue &, void_tag>::type q) + ArrayQueue(const ArrayQueue &q) requires std::copy_constructible<T> : _data((T*)malloc(sizeof(T) * q._capacity)), _capacity(q._capacity), _used(0), _skew(0) { try { diff --git a/vespalib/src/vespa/vespalib/util/small_vector.h b/vespalib/src/vespa/vespalib/util/small_vector.h index aaf8d848b54..b47cb5903b9 100644 --- a/vespalib/src/vespa/vespalib/util/small_vector.h +++ b/vespalib/src/vespa/vespalib/util/small_vector.h @@ -62,7 +62,7 @@ void create_objects(T *dst, uint32_t n, Args &&...args) { template <typename T> void destroy_objects(T *src, uint32_t n) { - if (!can_skip_destruction_v<T>) { + if (!can_skip_destruction<T>) { std::destroy_n(src, n); } } diff --git a/vespalib/src/vespa/vespalib/util/stash.h b/vespalib/src/vespa/vespalib/util/stash.h index 0d3558a26ab..a56865ac0ae 100644 --- a/vespalib/src/vespa/vespalib/util/stash.h +++ b/vespalib/src/vespa/vespalib/util/stash.h @@ -70,9 +70,9 @@ struct Chunk { * memory. * * When a stash is destructed, destruction of internal objects will be - * performed in reverse creation order. Objects for which the - * vespalib::can_skip_destruction trait is true are not - * destructed. This will save both time and space. + * performed in reverse creation order. Objects that satisfy the + * vespalib::can_skip_destruction concept are not destructed. This + * will save both time and space. * * The minimal chunk size of a stash is 4k. Any object larger than 1/4 * of the chunk size will be allocated separately. @@ -153,7 +153,7 @@ public: template <typename T, typename ... Args> T &create(Args && ... args) { - if (can_skip_destruction<T>::value) { + if (can_skip_destruction<T>) { return *(new (alloc(sizeof(T))) T(std::forward<Args>(args)...)); } using DeleteHook = stash::DestructObject<T>; @@ -165,7 +165,7 @@ public: template <typename T, typename ... Args> ArrayRef<T> create_array(size_t size, Args && ... args) { - if (can_skip_destruction<T>::value) { + if (can_skip_destruction<T>) { return ArrayRef<T>(init_array<T, Args...>(alloc(size * sizeof(T)), size, std::forward<Args>(args)...), size); } using DeleteHook = stash::DestructArray<T>; @@ -178,13 +178,13 @@ public: template <typename T> ArrayRef<T> create_uninitialized_array(size_t size) { static_assert(std::is_trivially_copyable_v<T>); - static_assert(can_skip_destruction<T>::value); + static_assert(can_skip_destruction<T>); return ArrayRef<T>(reinterpret_cast<T*>(alloc(size * sizeof(T))), size); } template <typename T> ArrayRef<T> copy_array(ConstArrayRef<T> src) { - if (can_skip_destruction<T>::value) { + if (can_skip_destruction<T>) { return ArrayRef<T>(copy_elements<T>(alloc(src.size() * sizeof(T)), src), src.size()); } using DeleteHook = stash::DestructArray<T>; diff --git a/vespalib/src/vespa/vespalib/util/traits.h b/vespalib/src/vespa/vespalib/util/traits.h index 7c39fd67812..bc87a7cb11d 100644 --- a/vespalib/src/vespa/vespalib/util/traits.h +++ b/vespalib/src/vespa/vespalib/util/traits.h @@ -8,41 +8,27 @@ namespace vespalib { //----------------------------------------------------------------------------- -namespace is_copyable_magic { -template <typename T> static const T& makeConstRef(); -template <typename T> static decltype(T(makeConstRef<T>()), 'y') check(int); -template <typename ...> static int check(...); -} - template <typename T> -struct is_copyable : std::integral_constant<bool, (sizeof(is_copyable_magic::check<T>(0)) == sizeof('y'))> {}; - -//----------------------------------------------------------------------------- - -struct void_tag { void_tag() = delete; }; - -//----------------------------------------------------------------------------- +constexpr bool enable_skip_destruction = false; template <typename T> -struct can_skip_destruction : std::is_trivially_destructible<T> {}; +concept can_skip_destruction = std::is_trivially_destructible_v<T> || enable_skip_destruction<T>; // Macro used to indicate that it is safe to skip destruction of // objects of class T. This macro can only be used in the global // namespace. This macro will typically be used to tag classes that do // not classify as trivially destructible because they inherit an // empty virtual destructor. -#define VESPA_CAN_SKIP_DESTRUCTION(T) \ - namespace vespalib { \ - template <> \ - struct can_skip_destruction<T> : std::true_type {}; \ +#define VESPA_CAN_SKIP_DESTRUCTION(MyType) \ + namespace vespalib { \ + template <> \ + constexpr bool enable_skip_destruction<MyType> = true; \ } -template <typename T> constexpr bool can_skip_destruction_v = can_skip_destruction<T>::value; //----------------------------------------------------------------------------- -template <typename, typename = std::void_t<>> struct has_type_type : std::false_type {}; -template <typename T> struct has_type_type<T, std::void_t<typename T::type>> : std::true_type {}; -template <typename T> constexpr bool has_type_type_v = has_type_type<T>::value; +template <typename T> +concept has_type_type = requires { typename T::type; }; //----------------------------------------------------------------------------- diff --git a/vespalib/src/vespa/vespalib/util/typify.h b/vespalib/src/vespa/vespalib/util/typify.h index 906c0c85710..3df59f488e5 100644 --- a/vespalib/src/vespa/vespalib/util/typify.h +++ b/vespalib/src/vespa/vespalib/util/typify.h @@ -79,7 +79,7 @@ template <size_t N, typename Typifier, typename Target, typename ...Rs> struct T return Typifier::resolve(value, [&](auto t)->decltype(auto) { using X = decltype(t); - if constexpr (has_type_type_v<X>) { + if constexpr (has_type_type<X>) { return TypifyInvokeImpl<N, Typifier, Target, Rs..., typename X::type>::select(std::forward<Args>(args)...); } else { return TypifyInvokeImpl<N, Typifier, Target, Rs..., X>::select(std::forward<Args>(args)...); |