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*.