diff --git a/include/beman/inplace_vector/inplace_vector.hpp b/include/beman/inplace_vector/inplace_vector.hpp index a031281..2409b23 100644 --- a/include/beman/inplace_vector/inplace_vector.hpp +++ b/include/beman/inplace_vector/inplace_vector.hpp @@ -57,10 +57,13 @@ using inplace_vector_internal_size_type = // array based storage is used so that we can satisfy constexpr requirement // -// Selecting this storage type implies: std::is_trivial_v +// Selecting this storage type implies: std::is_trivial_v or Capacity = 0 template struct inplace_vector_array_based_storage { - std::array elems; + using array_type = If, std::array, + const std::array, Capacity>>; + + array_type elems{}; constexpr T *begin() { return elems.data(); } constexpr const T *begin() const { return elems.data(); } @@ -69,7 +72,7 @@ struct inplace_vector_array_based_storage { // byte array based storage is used for non-constexpr environment, where default // initialization may not be available. // -// Selecting this storage type implies: !std::is_trivial_v +// Selecting this storage type implies: !std::is_trivial_v and Capacity != 0 template struct inplace_vector_bytes_based_storage { alignas(T) unsigned char elems[Capacity * sizeof(T)]; @@ -86,7 +89,7 @@ struct inplace_vector_destruct_base { using size_type = std::size_t; using internal_size_type = inplace_vector_internal_size_type; using internal_storage_type = - std::conditional_t, + std::conditional_t or Capacity == 0, inplace_vector_array_based_storage, inplace_vector_bytes_based_storage>; diff --git a/tests/beman/inplace_vector/constexpr.test.cpp b/tests/beman/inplace_vector/constexpr.test.cpp index f869bbc..c5a1822 100644 --- a/tests/beman/inplace_vector/constexpr.test.cpp +++ b/tests/beman/inplace_vector/constexpr.test.cpp @@ -16,51 +16,55 @@ struct NonTrivial { }; static_assert(!std::is_trivial_v); -static_assert(std::invoke([]() { - inplace_vector vec; +template constexpr bool test_empty_vec(T &vec) { - // sizes - S_ASSERT(vec.max_size() == 0); - S_ASSERT(vec.capacity() == 0); - S_ASSERT(vec.size() == 0); - S_ASSERT(vec.empty()); + // sizes + S_ASSERT(vec.max_size() == 0); + S_ASSERT(vec.capacity() == 0); + S_ASSERT(vec.size() == 0); + S_ASSERT(vec.empty()); - // itr - S_ASSERT(vec.begin() == vec.end()); - S_ASSERT(vec.cbegin() == vec.cend()); - S_ASSERT(vec.rbegin() == vec.rend()); - S_ASSERT(vec.crbegin() == vec.crend()); + // itr + S_ASSERT(vec.begin() == vec.end()); + S_ASSERT(vec.cbegin() == vec.cend()); + S_ASSERT(vec.rbegin() == vec.rend()); + S_ASSERT(vec.crbegin() == vec.crend()); - // push_back - S_ASSERT(vec.try_push_back(0) == nullptr); - S_ASSERT(vec.try_emplace_back(0) == nullptr); + // push_back + S_ASSERT(vec.try_push_back({}) == nullptr); + S_ASSERT(vec.try_emplace_back() == nullptr); + + return true; +} +static_assert(std::invoke([]() { + inplace_vector vec; + test_empty_vec(vec); return true; }), "0 capacity Trivial type"); static_assert(std::invoke([]() { - inplace_vector vec; - - // sizes - S_ASSERT(vec.max_size() == 0); - S_ASSERT(vec.capacity() == 0); - S_ASSERT(vec.size() == 0); - S_ASSERT(vec.empty()); - - // itr - S_ASSERT(vec.begin() == vec.end()); - S_ASSERT(vec.cbegin() == vec.cend()); - S_ASSERT(vec.rbegin() == vec.rend()); - S_ASSERT(vec.crbegin() == vec.crend()); - - // push_back - S_ASSERT(vec.try_push_back({}) == nullptr); + inplace_vector vec; + test_empty_vec(vec); + return true; + }), + "0 capacity Trivial const type"); +static_assert(std::invoke([]() { + inplace_vector vec; + test_empty_vec(vec); return true; }), "0 capacity Non-trivial type"); +static_assert(std::invoke([]() { + inplace_vector vec; + test_empty_vec(vec); + return true; + }), + "0 capacity Non-trivial const type"); + static_assert(std::invoke([]() { // sizes {