common/util/cpp/HsStdVariant.h (48 lines of code) (raw):
// Copyright (c) Facebook, Inc. and its affiliates.
#pragma once
#include <boost/mp11.hpp>
#include <glog/logging.h>
#include <variant>
#include "cpp/Marshallable.h"
namespace hs_std_variant::detail {
template <typename V>
void std_variant_poke(void* var, void* val, uint32_t idx) {
constexpr auto variant_size = std::variant_size_v<V>;
DCHECK_NE(idx, 0);
DCHECK_LT(idx, variant_size);
boost::mp11::mp_with_index<variant_size>(idx, [&](auto tag) {
using type = std::variant_alternative_t<tag, V>;
auto& val_ = *reinterpret_cast<type*>(val);
new (var) V{std::in_place_index<tag>, std::move(val_)};
});
}
} // namespace hs_std_variant::detail
// ****************************************************************************
#define hsc_derive_hs_std_variant_unsafe(cxx_name...) \
hsc_printf( \
"deriveHsStdVariantUnsafe \"%s\" %lu ", \
#cxx_name, \
(unsigned long)sizeof(hs_std_variant::cxx_name)); \
hsc_alignment(hs_std_variant::cxx_name);
#define HS_STD_VARIANT_H(Name, ...) \
namespace hs_std_variant { \
using Name = std::variant<std::monostate, __VA_ARGS__>; \
}
#define HS_STD_VARIANT_CPP(Name) \
HS_PEEKABLE(hs_std_variant::Name); \
HS_DEFINE_MARSHALLABLE(Name, hs_std_variant::Name); \
\
extern "C" void* std_variant_peek##Name(void* var, int32_t* idx) noexcept { \
constexpr auto variant_size = std::variant_size_v<hs_std_variant::Name>; \
auto& var_ = *reinterpret_cast<hs_std_variant::Name*>(var); \
*idx = var_.index(); \
DCHECK_GT(*idx, 0); \
DCHECK_LT(*idx, variant_size); \
return boost::mp11::mp_with_index<variant_size>(*idx, [&](auto tag) { \
return reinterpret_cast<void*>(&std::get<tag>(var_)); \
}); \
} \
\
extern "C" void std_variant_poke##Name( \
void* variant, void* val, int32_t tag) noexcept { \
hs_std_variant::detail::std_variant_poke<hs_std_variant::Name>( \
variant, val, tag); \
}