Date: Mon, 4 Dec 2023 07:08:07 +0000
On Mon, Dec 4, 2023 at 3:02 AM Arthur O'Dwyer wrote:
>
> What I think Thiago meant, and certainly what I mean, is that it's
> wrong to use [[no_unique_address]] on the `value` member of
> an `optional` or `expected`.
I think it's fine so long as you make it very obvious that you're not
allowed to use 'memcpy' or 'memset'. Maybe call it something like:
class optional_compacted_no_memset { . . . };
I was also thinking of writing something along the lines of an
'array_compacted' which would be the same as an 'std::array' except
that the elements have no padding between them, which would be very
useful for minimising Flash usage on a microcontroller -- something
like:
#include <cassert> // assert
#include <cstddef> // size_t
#include <cstdint> // uintptr_t
#include <cstring> // memcpy
template<typename T, std::size_t const len>
class array_compacted {
char unsigned buf[ __datasizeof(T) * len ];
class Manipulator {
void *const p;
public:
Manipulator(void *const arg) : p(arg) {};
void get(T *const arg) const noexcept
{
assert( 0u == (reinterpret_cast<std::uintptr_t>(arg) %
alignof(T)) );
std::memcpy(arg,p,__datasizeof(T));
}
void set(T const *const arg) noexcept
{
assert( 0u == (reinterpret_cast<std::uintptr_t>(arg) %
alignof(T)) );
std::memcpy(p,arg,__datasizeof(T));
}
};
public:
void Reset(void) { std::memset(buf,0,sizeof buf); }
Manipulator const operator[](std::size_t const i) const noexcept
{
assert( i < len );
return Manipulator{buf + __datasizeof(T)*i};
}
Manipulator operator[](std::size_t const i) noexcept
{
assert( i < len );
return Manipulator{buf + __datasizeof(T)*i};
}
};
struct Monkey {
long double a;
char b;
};
int main(void)
{
array_compacted<Monkey,256u> ac;
ac.Reset();
Monkey m;
ac[0u].get(&m);
m.b = 7;
ac[9u].set(&m);
}
>
> What I think Thiago meant, and certainly what I mean, is that it's
> wrong to use [[no_unique_address]] on the `value` member of
> an `optional` or `expected`.
I think it's fine so long as you make it very obvious that you're not
allowed to use 'memcpy' or 'memset'. Maybe call it something like:
class optional_compacted_no_memset { . . . };
I was also thinking of writing something along the lines of an
'array_compacted' which would be the same as an 'std::array' except
that the elements have no padding between them, which would be very
useful for minimising Flash usage on a microcontroller -- something
like:
#include <cassert> // assert
#include <cstddef> // size_t
#include <cstdint> // uintptr_t
#include <cstring> // memcpy
template<typename T, std::size_t const len>
class array_compacted {
char unsigned buf[ __datasizeof(T) * len ];
class Manipulator {
void *const p;
public:
Manipulator(void *const arg) : p(arg) {};
void get(T *const arg) const noexcept
{
assert( 0u == (reinterpret_cast<std::uintptr_t>(arg) %
alignof(T)) );
std::memcpy(arg,p,__datasizeof(T));
}
void set(T const *const arg) noexcept
{
assert( 0u == (reinterpret_cast<std::uintptr_t>(arg) %
alignof(T)) );
std::memcpy(p,arg,__datasizeof(T));
}
};
public:
void Reset(void) { std::memset(buf,0,sizeof buf); }
Manipulator const operator[](std::size_t const i) const noexcept
{
assert( i < len );
return Manipulator{buf + __datasizeof(T)*i};
}
Manipulator operator[](std::size_t const i) noexcept
{
assert( i < len );
return Manipulator{buf + __datasizeof(T)*i};
}
};
struct Monkey {
long double a;
char b;
};
int main(void)
{
array_compacted<Monkey,256u> ac;
ac.Reset();
Monkey m;
ac[0u].get(&m);
m.b = 7;
ac[9u].set(&m);
}
Received on 2023-12-04 07:08:19