サポートされているタイプの有限リストがある場合は、boostまたはstdバリアントを調べてください。
有限リストでない場合は、任意の(またはanyを含むバリアント)を押し上げるかstdします。
他の実装も見つけることができます。標準バージョンはC++ 17です。
簡略版の変種は、おそらく100行または2行のコードで記述することができます。
constexpr std::size_t max() { return 0; }
template<class...Ts>
constexpr std::size_t max(std::size_t t0, Ts...ts) {
return (t0<max(ts...))?max(ts...):t0;
}
template<class T0, class...Ts>
struct index_of_in;
template<class T0, class...Ts>
struct index_of_in<T0, T0, Ts...>:std::integral_constant<std::size_t, 0> {};
template<class T0, class T1, class...Ts>
struct index_of_in<T0, T1, Ts...>:
std::integral_constant<std::size_t,
index_of_in<T0, Ts...>::value+1
>
{};
struct variant_vtable {
void(*dtor)(void*) = 0;
void(*copy)(void*, void const*) = 0;
void(*move)(void*, void*) = 0;
};
template<class T>
void populate_vtable(variant_vtable* vtable) {
vtable->dtor = [](void* ptr){ static_cast<T*>(ptr)->~T(); };
vtable->copy = [](void* dest, void const* src){
::new(dest) T(*static_cast<T const*>(src));
};
vtable->move = [](void* dest, void* src){
::new(dest) T(std::move(*static_cast<T*>(src)));
};
}
template<class T>
variant_vtable make_vtable() {
variant_vtable r;
populate_vtable<T>(&r);
return r;
}
template<class T>
variant_vtable const* get_vtable() {
static const variant_vtable table = make_vtable<T>();
return &table;
}
template<class T0, class...Ts>
struct my_variant {
std::size_t index = -1;
variant_vtable const* vtable = 0;
static constexpr auto data_size = max(sizeof(T0),sizeof(Ts)...);
static constexpr auto data_align = max(alignof(T0),alignof(Ts)...);
template<class T>
static constexpr std::size_t index_of() {
return index_of_in<T, T0, Ts...>::value;
}
typename std::aligned_storage< data_size, data_align >::type data;
template<class T>
T* get() {
if (index_of<T>() == index)
return static_cast<T*>((void*)&data);
else
return nullptr;
}
template<class T>
T const* get() const {
return const_cast<my_variant*>(this)->get<T>();
}
template<class F, class R>
using applicator = R(*)(F&&, my_variant*);
template<class T, class F, class R>
static applicator<F, R> get_applicator() {
return [](F&& f, my_variant* ptr)->R {
return std::forward<F>(f)(*ptr->get<T>());
};
}
template<class F, class R=typename std::result_of<F(T0&)>::type>
R visit(F&& f) & {
if (index == (std::size_t)-1) throw std::invalid_argument("variant");
static const applicator<F, R> table[] = {
get_applicator<T0, F, R>(),
get_applicator<Ts, F, R>()...
};
return table[index](std::forward<F>(f), this);
}
template<class F,
class R=typename std::result_of<F(T0 const&)>::type
>
R visit(F&& f) const& {
return const_cast<my_variant*>(this)->visit(
[&f](auto const& v)->R
{
return std::forward<F>(f)(v);
}
);
}
template<class F,
class R=typename std::result_of<F(T0&&)>::type
>
R visit(F&& f) && {
return visit([&f](auto& v)->R {
return std::forward<F>(f)(std::move(v));
});
}
explicit operator bool() const { return vtable; }
template<class T, class...Args>
void emplace(Args&&...args) {
clear();
::new((void*)&data) T(std::forward<Args>(args)...);
index = index_of<T>();
vtable = get_vtable<T>();
}
void clear() {
if (!vtable) return;
vtable->dtor(&data);
index = -1;
vtable = nullptr;
}
~my_variant() { clear(); }
my_variant() {}
void copy_from(my_variant const& o) {
if (this == &o) return;
clear();
if (!o.vtable) return;
o.vtable->copy(&data, &o.data);
vtable = o.vtable;
index = o.index;
}
void move_from(my_variant&& o) {
if (this == &o) return;
clear();
if (!o.vtable) return;
o.vtable->move(&data, &o.data);
vtable = o.vtable;
index = o.index;
}
my_variant(my_variant const& o) {
copy_from(o);
}
my_variant(my_variant && o) {
move_from(std::move(o));
}
my_variant& operator=(my_variant const& o) {
copy_from(o);
return *this;
}
my_variant& operator=(my_variant&& o) {
move_from(std::move(o));
return *this;
}
template<class T,
typename std::enable_if<!std::is_same<typename std::decay<T>::type, my_variant>{}, int>::type =0
>
my_variant(T&& t) {
emplace<typename std::decay<T>::type>(std::forward<T>(t));
}
};
Live example:ここ
、粗製C++ 14変異体です。
C++ 11への変換は、ラムダをヘルパーに置き換えることで構成されます。私はC++ 11で書くのが好きではありません。このC++ 14は、ほとんどが機械的な変換です。
visit
はまったく変種をとり、他の理由の中でもとりわけ無効を返します。
コードはほとんど完全にテストされていませんが、デザインは健全です。
リモートシステムからどのように値を取得しますか?あなたが受け取ったデータのどこかに書かれた値のタイプですか? – bracco23
私はそれらをバイト配列として取得し、型に値が付いています。 – ruipacheco
リモートシステムから受信する生データの例を提供できますか? – bracco23