`<type_traits>`: `aligned_storage` has incorrect alignment defaults
Nobody has claimed this yet.
- Dominant language
- C++
- Stars
- 11.2k
- Forks
- 1.7k
- Avg merge
- 4d 15h
- Merged PRs (30d)
- 22
Description
[tab:meta.trans.other] specifies that default-alignment in
template<size_t Len, size_t Align = default-alignment>
struct aligned_storage;
"shall be the most stringent alignment requirement for any C++ object type whose size is no greater than Len". Since all valid alignments are powers of two, and the size of an object is always a multiple of its alignment, the default should be the largest power of two which divides Len evenly and is not greater than some upper bound. That upper bound is either alignof(max_align_t) (the largest fundamental alignment requirement) or some compiler-specific implementation limit on the largest possible alignment for an object type. I suspect the Standard intends the former, but I've asked LWG for clarification.
In any case, we should not be using alignof(max_align_t) as the default alignment for all sizes, which results in silliness like sizeof(aligned_storage<1>) == 8.
Command-line test case
(See https://godbolt.org/z/J7naDp)
C:\Users\Casey\Desktop>type repro.cpp
#include <cstddef>
#include <type_traits>
#include <utility>
using std::aligned_storage_t, std::index_sequence, std::max_align_t, std::size_t;
constexpr size_t alignment_for(size_t const Size) {
for (size_t alignment = 1; alignment < alignof(max_align_t); alignment *= 2) {
if (((alignment * 2 - 1) & Size) != 0) {
return alignment;
}
}
return alignof(max_align_t);
}
template <size_t Size>
constexpr void test_one() {
static_assert(alignof(aligned_storage_t<Size>) == alignment_for(Size));
static_assert(alignof(aligned_storage_t<Size>) != alignof(max_align_t));
static_assert(sizeof(aligned_storage_t<Size>) == Size);
}
template <size_t... Sizes>
constexpr void test(index_sequence<Sizes...>) {
(test_one<Sizes + 1>(), ...);
}
static_assert((test(std::make_index_sequence<alignof(max_align_t) - 1>{}), true));
static_assert(alignof(aligned_storage_t<2 * alignof(max_align_t)>) == alignof(max_align_t));
C:\Users\Casey\Desktop>cl /nologo /std:c++17 /permissive- repro.cpp
repro.cpp
repro.cpp(18): error C2607: static assertion failed
repro.cpp(24): note: see reference to function template instantiation 'void test_one<1>(void)' being compiled
repro.cpp(28): note: see reference to function template instantiation 'void test<0,1,2,3,4,5,6>(std::integer_sequence<size_t,0,1,2,3,4,5,6>)' being compiled
repro.cpp(28): note: while evaluating constexpr function 'test'
repro.cpp(19): error C2607: static assertion failed
repro.cpp(28): note: while evaluating constexpr function 'test'
repro.cpp(20): error C2607: static assertion failed
repro.cpp(28): note: while evaluating constexpr function 'test'
vNext note: Resolving this issue will require breaking binary compatibility. We won't be able to accept pull requests for this issue until the vNext branch is available. See #169 for more information.
Additional Context
Skipped libcxx test
https://github.com/microsoft/STL/blob/06827feb4cdc4d2328dfbfab9fd5302de6058dd9/tests/libcxx/expected_results.txt#L644-L645
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the <type_traits> aligned_storage implementation and the libcxx expectation entry at tests/libcxx/expected_results.txt#L644-L645; use the provided C++17 repro to confirm the current alignment and size behavior. Resolve the Standard/LWG question and vNext binary-compatibility constraint before changing behavior; done means the test is no longer skipped and the repro assertions pass.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp
- Domain
- tooling
- Issue type
- Bug
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 25/100