summaryrefslogtreecommitdiffstats
path: root/vespalib
diff options
context:
space:
mode:
authorHåvard Pettersen <havardpe@yahooinc.com>2022-09-21 09:43:28 +0000
committerHåvard Pettersen <havardpe@yahooinc.com>2022-09-21 11:47:13 +0000
commit95e8f34f7ee1e7df1db7ef52a189245289d51598 (patch)
tree20297f587675316621a4dd943f75923ad85de6cd /vespalib
parent04b195343586990e6a612d33e98c7fa8603ee0f4 (diff)
use more concepts
Diffstat (limited to 'vespalib')
-rw-r--r--vespalib/src/tests/datastore/array_store/array_store_test.cpp4
-rw-r--r--vespalib/src/tests/datastore/unique_store/unique_store_test.cpp4
-rw-r--r--vespalib/src/tests/stash/stash.cpp4
-rw-r--r--vespalib/src/tests/traits/traits_test.cpp27
-rw-r--r--vespalib/src/vespa/vespalib/stllike/hashtable.h2
-rw-r--r--vespalib/src/vespa/vespalib/util/arrayqueue.hpp5
-rw-r--r--vespalib/src/vespa/vespalib/util/small_vector.h2
-rw-r--r--vespalib/src/vespa/vespalib/util/stash.h14
-rw-r--r--vespalib/src/vespa/vespalib/util/traits.h30
-rw-r--r--vespalib/src/vespa/vespalib/util/typify.h2
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)...);