Skip to content

Do not use std::aligned_storage#47

Open
alt-graph wants to merge 7 commits into
mainfrom
cleanup/do_not_use_std_aligned_storage
Open

Do not use std::aligned_storage#47
alt-graph wants to merge 7 commits into
mainfrom
cleanup/do_not_use_std_aligned_storage

Conversation

@alt-graph
Copy link
Copy Markdown
Member

[why]

std::aligned_storage is deprecated since C++23, see: https://stackoverflow.com/questions/71828288/why-is-stdaligned-storage-to-be-deprecated-in-c23-and-what-to-use-instead

[how]

Use alignas() for the internal buffer and specify the alignment explicitly when calling new for an allocated buffer. As it turns out, an aligned new[] has to be deallocated with an aligned delete[], so we have to change that handling, too. We also had no unit test for the alignment requirements, so we add one.

alt-graph added 3 commits May 21, 2026 15:57
[why]
We should verify that SmallVector actually places its elements according
to their alignment requirements. As it turns out, it does. :)
[why]
std::aligned_storage is deprecated since C++23, see:
https://stackoverflow.com/questions/71828288/why-is-stdaligned-storage-to-be-deprecated-in-c23-and-what-to-use-instead

[how]
Use alignas() for the internal buffer and specify the alignment
explicitly when calling new for an allocated buffer. As it turns out,
an aligned new[] has to be deallocated with an aligned delete[].
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates gul17::SmallVector to avoid using std::aligned_storage (deprecated in C++23) by switching to an alignas(...)-aligned internal byte buffer and using aligned new[] / delete[] for heap storage. It also adds a unit test to validate alignment after growth and shrink_to_fit().

Changes:

  • Replace std::aligned_storage with an alignas(ValueType) internal std::byte buffer and aligned heap allocation/deallocation.
  • Add an alignment regression test that exercises push_back() growth and shrink_to_fit() transitions.
  • Update changelog/copyright headers.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 5 comments.

File Description
include/gul17/SmallVector.h Reworks internal/heap storage to avoid std::aligned_storage and uses aligned new[]/delete[].
tests/test_SmallVector.cc Adds a new template test to verify element alignment and contiguity across growth/shrink.
data/doxygen.h Updates the “Unreleased” changelog section.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread include/gul17/SmallVector.h Outdated
Comment thread include/gul17/SmallVector.h Outdated
Comment thread include/gul17/SmallVector.h Outdated
Comment on lines +1308 to +1314
void deallocate_storage() noexcept
{
if (!is_storage_allocated())
return;

::operator delete[](data_ptr_, alignment);
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

gcc with -fanalyzer points this out as well.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Copilot "fix" is bull****, but I see how leaving the pointer dangling at the end of the function may arouse suspicion. I'll add a commit in which the pointer is set to null if a deallocation took place and I'll state explicitly that the class invariants are temporarily broken when this happens.

The only other way out I see here is to remove the helper function again and inline the instructions, as it was before.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The only other way out I see here is to remove the helper function again and inline the instructions, as it was before.

With the latest commit I have taken that route. It is probably better than having a member function that breaks the class invariants, even if it is private.

Comment thread tests/test_SmallVector.cc
Comment thread data/doxygen.h
[why]
The function could leave data_ptr_ dangling after the call. This was
clearly documented and logically OK within the class, but could raise
suspicion.

[how]
Explicitly document that the function may leave the class in a state in
which the class invariants are violated. If deallocation takes place,
assign nullptr to data_ptr_ so that there is a better chance to find
misuses.
@alt-graph alt-graph marked this pull request as draft May 22, 2026 08:07
@alt-graph alt-graph marked this pull request as ready for review May 22, 2026 08:25
alt-graph added 3 commits May 22, 2026 10:39
[why]
MSVC mistakes the statement

allocation = new (alignment) std::byte[new_capacity * sizeof(ValueType)];

for a placement new even if alignment is of the type std::align_val_t,
and therefore generates a compilation error.

[how]
Use the low-level form of new directly like this:

auto* ptr = static_cast<std::byte*>(
    ::operator new[](num_elements * sizeof(ValueType), alignment));

Because this is ugly, extract both allocation and deallocation into
static member functions.
[why]
Having a private member function that breaks the class invariants may be
confusing, and it does not make things any clearer than having the two
lines directly in the code.
@alt-graph alt-graph force-pushed the cleanup/do_not_use_std_aligned_storage branch from f3533f0 to 7c0ab98 Compare May 22, 2026 08:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants