From d089482467d4099dcd5030a18de8d7222a923424 Mon Sep 17 00:00:00 2001 From: KRM7 <70973547+KRM7@users.noreply.github.com> Date: Mon, 5 Feb 2024 22:46:40 +0100 Subject: [PATCH] fix object layout --- src/small_vector.hpp | 33 +++++++++++++++++++++------------ test/small_vector.cpp | 18 ++++++++++++++++++ 2 files changed, 39 insertions(+), 12 deletions(-) diff --git a/src/small_vector.hpp b/src/small_vector.hpp index a4358e0..abae0e9 100644 --- a/src/small_vector.hpp +++ b/src/small_vector.hpp @@ -18,12 +18,10 @@ #include #include -#if defined(_MSC_VER) && !defined(__clang__) +#if defined(_MSC_VER) # define SV_NO_UNIQUE_ADDRESS [[msvc::no_unique_address]] -#elif __has_cpp_attribute(no_unique_address) -# define SV_NO_UNIQUE_ADDRESS [[no_unique_address]] #else -# define SV_NO_UNIQUE_ADDRESS +# define SV_NO_UNIQUE_ADDRESS [[no_unique_address]] #endif namespace detail @@ -320,7 +318,7 @@ namespace detail inline constexpr std::size_t cache_line_size = 64; - template + template struct small_vector_buffer { public: @@ -335,15 +333,25 @@ namespace detail constexpr std::size_t size() const noexcept { return Size; } private: - inline constexpr static std::size_t align_req = std::max(alignof(T), Align); - union { unsigned char dummy_ = {}; - alignas(align_req) std::array data_; + std::array data_; }; }; + template + struct small_vector_buffer + { + constexpr T* begin() noexcept { return nullptr; } + constexpr const T* begin() const noexcept { return nullptr; } + + constexpr T* end() noexcept { return nullptr; } + constexpr const T* end() const noexcept { return nullptr; } + + constexpr std::size_t size() const noexcept { return 0; } + }; + template struct default_small_size @@ -896,15 +904,16 @@ class small_vector } private: + static constexpr double growth_factor = 1.618; + static constexpr std::size_t alignment = !!Size * std::max(alignof(T), detail::cache_line_size); - detail::small_vector_buffer buffer_; + alignas(alignment) + SV_NO_UNIQUE_ADDRESS detail::small_vector_buffer buffer_; pointer first_ = nullptr; pointer last_ = nullptr; pointer last_alloc_ = nullptr; SV_NO_UNIQUE_ADDRESS allocator_type alloc_; - static inline constexpr double growth_factor_ = 1.618; - constexpr void allocate_n(size_type count) { @@ -988,7 +997,7 @@ class small_vector constexpr size_type next_capacity(size_type min_capacity = 0) const noexcept { - return std::max(min_capacity, size_type(growth_factor_ * capacity()) + 1); + return std::max(min_capacity, size_type(growth_factor * capacity()) + 1); } }; // class small_vector diff --git a/test/small_vector.cpp b/test/small_vector.cpp index fbfaecc..8815c11 100644 --- a/test/small_vector.cpp +++ b/test/small_vector.cpp @@ -84,6 +84,24 @@ constexpr auto equal_to(T rhs) } + //-----------------------------------// + // OBJECT LAYOUT // + //-----------------------------------// + + +TEST_CASE("small_vector_size", "[object_layout][!mayfail]") // fails under clang-cl because of no support for no_unique_address +{ + STATIC_REQUIRE(std::is_standard_layout_v>); + STATIC_REQUIRE(std::is_standard_layout_v>); + + CHECK(sizeof(small_vector) == detail::cache_line_size); + CHECK(alignof(small_vector) == detail::cache_line_size); + + CHECK(sizeof(small_vector) == 3 * sizeof(int*)); + CHECK(alignof(small_vector) == alignof(int*)); +} + + //-----------------------------------// // CONSTRUCTORS // //-----------------------------------//