Date: Sun, 13 Apr 2025 10:43:34 +0100
On Saturday, April 12, 2025, Henning Meyer wrote:
>
> I would like to work generically with std::variant and std::any.
>
>
Not particularly relevant to this topic, but I think two or three years ago
I wrote a class that is kind of halfway between 'variant' and 'any'.
Basically you had all the benefits of 'any' except that it didn't
dynamically allocate. So you had to specify a maximum size for the object,
sort of like:
template<size_t N = 256zu>
class any_variant {
constexpr std::size_t N = N;
alignas(max_align_t) byte buf[N];
type_info const *pti = nullptr;
void (*destructor)(void*) noexcept = nullptr;
};
The best thing about it was that you got a compiler error (rather than a
runtime error) if you tried to host an object that didn't fit, like this:
template<typename Tref>
constexpr any_variant &operator=(Tref &&arg)
noexcept(noexcept(remove_cvref_t<Tref>(Tref&&)))
{
static_assert( N >= sizeof arg );
if ( destructor )
{
destructor(buf); // better not throw
destructor = nullptr;
pti = nullptr;
}
typedef remove_cvref_t<Tref> T;
construct_at<T>( (T*)buf, forward<Tref>(arg) );
pti = &typeid(T);
destructor = +[](void *const arg) noexcept
{
((T*)arg)->~T(); // better not throw
};
}
Might need compiler support to make it 'constexpr' because I cast a void*
to a T*.
>
> I would like to work generically with std::variant and std::any.
>
>
Not particularly relevant to this topic, but I think two or three years ago
I wrote a class that is kind of halfway between 'variant' and 'any'.
Basically you had all the benefits of 'any' except that it didn't
dynamically allocate. So you had to specify a maximum size for the object,
sort of like:
template<size_t N = 256zu>
class any_variant {
constexpr std::size_t N = N;
alignas(max_align_t) byte buf[N];
type_info const *pti = nullptr;
void (*destructor)(void*) noexcept = nullptr;
};
The best thing about it was that you got a compiler error (rather than a
runtime error) if you tried to host an object that didn't fit, like this:
template<typename Tref>
constexpr any_variant &operator=(Tref &&arg)
noexcept(noexcept(remove_cvref_t<Tref>(Tref&&)))
{
static_assert( N >= sizeof arg );
if ( destructor )
{
destructor(buf); // better not throw
destructor = nullptr;
pti = nullptr;
}
typedef remove_cvref_t<Tref> T;
construct_at<T>( (T*)buf, forward<Tref>(arg) );
pti = &typeid(T);
destructor = +[](void *const arg) noexcept
{
((T*)arg)->~T(); // better not throw
};
}
Might need compiler support to make it 'constexpr' because I cast a void*
to a T*.
Received on 2025-04-13 09:43:37