Date: Thu, 07 Dec 2023 08:00:48 +0000
On Wed, 2023-12-06 at 17:01 +0000, Frederick Virchanza Gotham via Std-
Proposals wrote:
> On Wed, Dec 6, 2023 at 4:52 PM Gašper Ažman wrote:
> >
> > ++ for unaligned<trivial>
>
>
> So how would "std::unaligned<Trivial>" work? Would it lack tail
> padding? Or would it lack tail padding and also lack padding between
> members?
std::unaligned would be applied to the members, not the enclosing
class, like so:
struct Monkey {
std::unaligned<long> l;
char ch;
};
static_assert(sizeof(Monkey) == sizeof(long) + sizeof(char));
std::unaligned could be implemented something like this:
template <typename T, std::size_t alignment = 1>
requires (std::popcount(alignment) == 1)
class unaligned {
static_assert(std::is_trivially_copyable_v<T>);
using storage_t = std::array<std::byte, sizeof(T)>;
alignas(alignment) storage_t m_storage;
public:
constexpr unaligned(T t) noexcept
: m_storage(std::bit_cast<storage_t>(t))
{}
constexpr operator T() noexcept {
return std::bit_cast<T>(m_storage);
}
};
You also identified the problem of taking address of packed members and
the potential need for special treatment of them in the language. If
implemented like above then you don't need special treatment in the
language, you can't take the address and get a `long *` out of an
unaligned<long>.
>
> So if I have a trivial standard-layout struct as follows:
>
> struct Monkey {
> long unsigned a;
> char b;
> // padding here?
> long double c;
> char d;
> // padding here?
> float e;
> char f;
> // padding here?
> };
>
> Then what will std::unaligned<Monkey> do? Will it take out just the
> tail padding, or will it take out the 3 pieces of padding?
Proposals wrote:
> On Wed, Dec 6, 2023 at 4:52 PM Gašper Ažman wrote:
> >
> > ++ for unaligned<trivial>
>
>
> So how would "std::unaligned<Trivial>" work? Would it lack tail
> padding? Or would it lack tail padding and also lack padding between
> members?
std::unaligned would be applied to the members, not the enclosing
class, like so:
struct Monkey {
std::unaligned<long> l;
char ch;
};
static_assert(sizeof(Monkey) == sizeof(long) + sizeof(char));
std::unaligned could be implemented something like this:
template <typename T, std::size_t alignment = 1>
requires (std::popcount(alignment) == 1)
class unaligned {
static_assert(std::is_trivially_copyable_v<T>);
using storage_t = std::array<std::byte, sizeof(T)>;
alignas(alignment) storage_t m_storage;
public:
constexpr unaligned(T t) noexcept
: m_storage(std::bit_cast<storage_t>(t))
{}
constexpr operator T() noexcept {
return std::bit_cast<T>(m_storage);
}
};
You also identified the problem of taking address of packed members and
the potential need for special treatment of them in the language. If
implemented like above then you don't need special treatment in the
language, you can't take the address and get a `long *` out of an
unaligned<long>.
>
> So if I have a trivial standard-layout struct as follows:
>
> struct Monkey {
> long unsigned a;
> char b;
> // padding here?
> long double c;
> char d;
> // padding here?
> float e;
> char f;
> // padding here?
> };
>
> Then what will std::unaligned<Monkey> do? Will it take out just the
> tail padding, or will it take out the 3 pieces of padding?
Received on 2023-12-07 08:00:56