如果存在支持類型的有限列表,則檢查boost或std變體。
如果不是有限的列表,boost或std any(或包含any的變體)。
你也可以找到其他的實現。標準版本在C++ 17中。
變體的簡化版本可能會寫入100或兩行代碼。
這裏是一個粗C++ 14變體:
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++ 11將包含一堆替換帶助手的lambdas。我不喜歡用C++ 11編寫,而這個C++ 14是遠離它的大多數機械轉換。
原因很簡單,因爲visit
只需要一個變體並返回無效等等原因。
代碼幾乎完全未經測試,但設計很完善。
如何從遠程系統獲取值?是收到的數據中收到的價值類型? – bracco23
我得到他們作爲一個字節數組和類型確實帶有值。 – ruipacheco
您能提供一個您將從遠程系統收到的原始數據的例子嗎? – bracco23