How to replace aligned_storage<T[]> with std::byte[]?
Asked Answered
A

2

5

The use of aligned_storage is deprecated in C++23 and suggested to be replaced with an aligned std::byte[] (see here). I have two questions about this:

1. How to align this?

The document suggests to replace

std::aligned_storage_t<sizeof(T), alignof(T)> t_buff; with

alignas(T) std::byte t_buff[sizeof(T)].

However, I am actually storing an array of T (or T is an array of something). Can I simply replace std::aligned_storage_t<sizeof(T), alignof(T)> data_[SIZE]; with

alignas(alignof(T)*SIZE) std::byte data_[sizeof(T) * SIZE]; ?

I think this is a wrong usage of alignas or not?

2. How to read/write?

I think access has not changed much, so is it correct to read with:

reference data(size_t index) noexcept {
    return *std::launder(reinterpret_cast<T*>(&data_[index*sizeof(T)]));
}

and write with

new (reinterpret_cast<void*>(&data_[size_*sizeof(T)])) T{std::forward<Args>(args)...}; ?

Why am I asking?

My use of alignas seems really wrong, how should I align it? Can I really just multiply access index with sizeof(T), or do I need take padding into account? How?

Also, the code somehow seems worse than before because I have to insert sizeof() everywhere.

It seems to work when I run it but I am not sure whether this is really save.

I looked at other examples (e.g. here, here and others) but they always have T instead of T[] as an example.

Applecart answered 16/2, 2023 at 18:16 Comment(2)
Why not use alignas(T[SIZE]) std::byte t_buff[sizeof(T[SIZE])]?Malley
@Malley make that an answerLinnell
M
8

You do not need to do anything different. Per [expr.alignof]/3 the alignement of T[N] is the alignment of T so you can just use

alignas(T) std::byte data_[sizeof(T) * SIZE];

You could also just use the alignment and size of the array iteself like

alignas(T[SIZE]) std::byte t_buff[sizeof(T[SIZE])]
Malley answered 16/2, 2023 at 18:31 Comment(0)
T
1

You have std::aligned_storage_t<sizeof(T), alignof(T)> data_[SIZE]. The document suggests replacing the aligned storage with an array, so you get a multidimensional array:

    alignas(T) std::byte data_[SIZE][sizeof(T)];

And this should be accessed about the same as your previous array of aligned_storage.

You can also make this a single-dimensional array alignas(T) std::byte data_[SIZE*sizeof(T)], but there's not much benefit (as you noted, you need &data_[i*sizeof(V)] to get a pointer to the ith element, where with the multidimensional array you can use data_[i])

Typecase answered 16/2, 2023 at 18:31 Comment(2)
I'd prefer a 1D array. Rules for multidimensional arrays are wonky. Depending on how you form a pointer to it, you may or may not be only allowed to index the first sub-array.Quizzical
@Typecase Thanks, interesting suggestion but I'll go with a 1D array.Applecart

© 2022 - 2024 — McMap. All rights reserved.