Skip to content

Commit

Permalink
Make amc::vector declaration work with incomplete types like std::vector
Browse files Browse the repository at this point in the history
  • Loading branch information
sjanel committed Sep 1, 2021
1 parent 18ff2c4 commit 8768eec
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 14 deletions.
39 changes: 25 additions & 14 deletions src/include/amc_vectorcommon.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1040,8 +1040,7 @@ struct VectorBaseTypeDispatcher {
/// VectorDestr simply defines a destructor for non trivially destructible T's, and stays trivially destructible for
/// trivially destructible T's.
/// There is no way to SFINAE the destructor so we use a derived class here.
template <class T, class Alloc, class SizeType, bool WithInlineElements, class GrowingPolicy,
bool TriviallyDestructible>
template <class T, class Alloc, class SizeType, bool WithInlineElements, class GrowingPolicy, bool DefineDestructor>
class VectorDestr : public VectorBaseTypeDispatcher<T, Alloc, SizeType, WithInlineElements, GrowingPolicy>::type {
public:
~VectorDestr() { amc::destroy_n(this->begin(), this->size()); }
Expand All @@ -1054,7 +1053,7 @@ class VectorDestr : public VectorBaseTypeDispatcher<T, Alloc, SizeType, WithInli
};

template <class T, class Alloc, class SizeType, bool WithInlineElements, class GrowingPolicy>
class VectorDestr<T, Alloc, SizeType, WithInlineElements, GrowingPolicy, true>
class VectorDestr<T, Alloc, SizeType, WithInlineElements, GrowingPolicy, false>
: public VectorBaseTypeDispatcher<T, Alloc, SizeType, WithInlineElements, GrowingPolicy>::type {
protected:
template <class... Args>
Expand All @@ -1063,10 +1062,18 @@ class VectorDestr<T, Alloc, SizeType, WithInlineElements, GrowingPolicy, true>
std::forward<Args &&>(args)...) {}
};

/// This macro allows usage of incomplete type for amc::vector, while keeping possibility for a FixedCapacityVector of a
/// trivially destructible type to stay trivially destructible
template <class T, bool WithInlineElements>
struct DefineDestructor : std::integral_constant<bool, !std::is_trivially_destructible<T>::value> {};

template <class T>
struct DefineDestructor<T, false> : std::integral_constant<bool, true> {};

/// Implementation class with definitions independent from the traits of type T and number of elements
template <class T, class Alloc, class SizeType, bool WithInlineElements, class GrowingPolicy>
class VectorImpl : public VectorDestr<T, Alloc, SizeType, WithInlineElements, GrowingPolicy,
std::is_trivially_destructible<T>::value> {
DefineDestructor<T, WithInlineElements>::value> {
public:
using value_type = T;
using iterator = T *;
Expand Down Expand Up @@ -1345,8 +1352,8 @@ class VectorImpl : public VectorDestr<T, Alloc, SizeType, WithInlineElements, Gr
protected:
template <class... Args>
explicit VectorImpl(Args &&...args) noexcept
: VectorDestr<T, Alloc, SizeType, WithInlineElements, GrowingPolicy, std::is_trivially_destructible<T>::value>(
std::forward<Args &&>(args)...) {}
: VectorDestr<T, Alloc, SizeType, WithInlineElements, GrowingPolicy,
DefineDestructor<T, WithInlineElements>::value>(std::forward<Args &&>(args)...) {}
};

template <class T, class A, class S, bool I, class G>
Expand All @@ -1369,11 +1376,19 @@ class VectorWithInplaceStorage : public VectorImpl<T, Alloc, SizeType, true, Gro
_elems[N - (std::is_same<GrowingPolicy, vec::DynamicGrowingPolicy>::value ? ElemWithPtrStorage<T>::kNbSlots : 1)];
};

template <class T, class GrowingPolicy, uintmax_t N>
struct NoInlineStorage : std::integral_constant<bool, std::is_same<GrowingPolicy, vec::DynamicGrowingPolicy>::value &&
(N <= vec::ElemWithPtrStorage<T>::kNbSlots)> {};

template <class T, class GrowingPolicy>
struct NoInlineStorage<T, GrowingPolicy, 0> : std::integral_constant<bool, true> {};

template <class T, class GrowingPolicy>
struct NoInlineStorage<T, GrowingPolicy, 1> : std::integral_constant<bool, true> {};

template <class T, class Alloc, class SizeType, class GrowingPolicy, SizeType N>
class VectorWithInplaceStorage<
T, Alloc, SizeType, GrowingPolicy, N,
typename std::enable_if<(N <= 1) || (std::is_same<GrowingPolicy, vec::DynamicGrowingPolicy>::value &&
(N <= vec::ElemWithPtrStorage<T>::kNbSlots))>::type>
class VectorWithInplaceStorage<T, Alloc, SizeType, GrowingPolicy, N,
typename std::enable_if<NoInlineStorage<T, GrowingPolicy, N>::value>::type>
: public VectorImpl<T, Alloc, SizeType, (N != 0), GrowingPolicy> {
protected:
template <class... Args>
Expand All @@ -1383,11 +1398,7 @@ class VectorWithInplaceStorage<

template <uintmax_t N, class SizeType>
constexpr SizeType SanitizeInlineSize() {
#ifdef AMC_CXX14
static_assert(std::less_equal<uintmax_t>()(N, static_cast<uintmax_t>(std::numeric_limits<SizeType>::max())),
#else
static_assert(N <= static_cast<uintmax_t>(std::numeric_limits<SizeType>::max()),
#endif
"Inline storage too large for SizeType");
return static_cast<SizeType>(N);
}
Expand Down
9 changes: 9 additions & 0 deletions src/test/vectors_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -509,4 +509,13 @@ TEST(VectorTest, SmallVectorOptimizedSizeInt) {
EXPECT_EQ(ints, SmallInt16SmallVector({42, -56, -56, 42, 42, 37, 7567}));
}

TEST(VectorTest, IncompleteType) {
struct Foo {
amc::vector<Foo> v;
};

Foo f;
EXPECT_TRUE(f.v.empty());
}

} // namespace amc

0 comments on commit 8768eec

Please sign in to comment.