Date: Sun, 13 Apr 2025 13:41:04 +0200
I believe there are many custom implementations of std::function and
std::any with a small buffer optimization in production code bases, just
as there are many hash map implementations. And std::expected-clones for
code bases not yet fully converted to C++23. From a semantics
perspective, std::expected<R,E> is quite different from
std::variant<R,E>, but from a tooling perspective they pose the same
problem of finding out which state the variable is in and how to get the
contained object.
On 13.04.25 11:43, Frederick Virchanza Gotham via Std-Proposals wrote:
>
>
> 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*.
>
>
>
>
>
std::any with a small buffer optimization in production code bases, just
as there are many hash map implementations. And std::expected-clones for
code bases not yet fully converted to C++23. From a semantics
perspective, std::expected<R,E> is quite different from
std::variant<R,E>, but from a tooling perspective they pose the same
problem of finding out which state the variable is in and how to get the
contained object.
On 13.04.25 11:43, Frederick Virchanza Gotham via Std-Proposals wrote:
>
>
> 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*.
>
>
>
>
>
Received on 2025-04-13 11:41:07