Skip to content

Commit

Permalink
fix object layout
Browse files Browse the repository at this point in the history
  • Loading branch information
KRM7 committed Feb 6, 2024
1 parent 97012ec commit d089482
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 12 deletions.
33 changes: 21 additions & 12 deletions src/small_vector.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,10 @@
#include <cstddef>
#include <cassert>

#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
Expand Down Expand Up @@ -320,7 +318,7 @@ namespace detail

inline constexpr std::size_t cache_line_size = 64;

template<typename T, std::size_t Size, std::size_t Align = cache_line_size>
template<typename T, std::size_t Size>
struct small_vector_buffer
{
public:
Expand All @@ -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<T, Size> data_;
std::array<T, Size> data_;
};
};

template<typename T>
struct small_vector_buffer<T, 0>
{
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<typename T>
struct default_small_size
Expand Down Expand Up @@ -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<T, Size> buffer_;
alignas(alignment)
SV_NO_UNIQUE_ADDRESS detail::small_vector_buffer<T, Size> 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)
{
Expand Down Expand Up @@ -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
Expand Down
18 changes: 18 additions & 0 deletions test/small_vector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<small_vector<int>>);
STATIC_REQUIRE(std::is_standard_layout_v<small_vector<int, 0>>);

CHECK(sizeof(small_vector<int>) == detail::cache_line_size);
CHECK(alignof(small_vector<int>) == detail::cache_line_size);

CHECK(sizeof(small_vector<int, 0>) == 3 * sizeof(int*));
CHECK(alignof(small_vector<int, 0>) == alignof(int*));
}


//-----------------------------------//
// CONSTRUCTORS //
//-----------------------------------//
Expand Down

0 comments on commit d089482

Please sign in to comment.