我有15分鐘。傳入標記的聯盟。不如boost::variant
,我可能不會編譯它,但它應該讓你開始。
template<size_t S>
using size = std::integral_constant<std::size_t, S>;
template<bool b>
using bool_t = std::integral_constant<bool, b>;
template<size_t...Ss>
struct max_size:size<0>{};
template<size_t S0, size_t...Ss>
struct max_size:size<(std::max)(S0, max_size<Ss...>{}())>{};
template<class...Ts>
struct max_alignof : max_size< alignof(Ts)... >{};
template<class...Ts>
struct max_sizeof : max_size< sizeof(Ts)... >{};
template<class X>struct tag{using type=X;};
template<class...>struct types{using type=types;};
template<class Tag>using type_t=typename Tag::type;
template<class T, class Types>
struct index_of {};
template<class T, class...Ts>
struct index_of<T, types<T,Ts...>>:size<0>{};
template<class T, class T0, class...Ts>
struct index_of<T, types<T0,Ts...>>:size<
index_of<T, types<Ts...>>{}+1
>{};
template<class X>
struct emplace_as {};
template<class F, class...Ts>
void invoke(types<Ts...>, void* p, F&& f, size_t i) {
auto* pf = std::addressof(f);
using operation=void(*)(decltype(pf), void*);
operation table[]={
+[](decltype(pf), void* p){
Ts* pt = static_cast<Ts*>(p);
std::forward<F>(*pf)(*pt);
}...
};
table[i](pf, p);
}
template<class T0, class...Ts>
struct one_of {
std::aligned_storage< max_sizeof<T0, Ts...>{}, max_alignof<T0, Ts...>{} > data;
size_t index = -1;
using my_types = types<T0, Ts...>;
template<class T>
using sfinae_my_type = tag< size<index_of<X,my_types>{}> >;
one_of():one_of(emplace_as<T0>{}) {}
// brace construction support for only the first type:
one_of(T0&&t0):one_of(emplace_as<T0>{}, std::move(t0)) {}
template<class X, class...Args, class=sfinae_my_type<X>>
one_of(emplace_as<X>, Args&&... args){
emplace(emplace_as<X>{}, std::forward<Args>(args)...);
}
template<class X, class=sfinae_my_type<std::decay_t<X>>>
one_of(X&& x) {
emplace_as(std::forward<X>(x));
}
template<class X, class=sfinae_my_type<X>>
X* get() {
if (index_of<X, my_types>{}==index) {
return static_cast<X*>(&data);
} else {
return nullptr;
}
}
template<class X, class=sfinae_my_type<X>>
X const* get() const {
if (index_of<X, my_types>{}==index) {
return static_cast<X const*>(&data);
} else {
return nullptr;
}
}
template<class X, class=sfinae_my_type<std::decay_t<X>>>
void emplace(X&& x) {
emplace_as<std::decay_t<X>>{}, std::forward<X>(x));
}
template<class X, class...Args, class=sfinae_my_type<X>>
void emplace(emplace_as<X>, Args&&...args) {
destroy();
new(&data) X(std::forward<Args>(args)...);
index = index_of<X, list<T0, Ts...>>{};
}
template<class F>
void my_invoke(F&& f) {
my_invoke(std::forward<F>(f), index);
}
template<class F>
void apply(F&& f) {
invoke(my_types{}, &data, std::forward<F>(f), index);
}
void destroy() {
if (index != -1) {
apply([&](auto&& x){
using X=std::decay_t<decltype(x)>;
index = -1;
x.~X();
});
};
}
one_of& operator=(one_of const& rhs){
if (this == &rhs) return *this;
destroy();
rhs.apply([&](auto const& x) {
using X=std::decay_t<decltype(x)>;
emplace(emplace_as<X>{}, decltype(x)(x));
});
return *this;
}
one_of& operator=(one_of&& rhs){
if (this == &rhs) return *this;
destroy();
rhs.apply([&](auto & x) {
using X=std::decay_t<decltype(x)>;
emplace(emplace_as<X>{}, std::move(x));
});
return *this;
}
~one_of(){destroy();}
};
這是一個標記聯合類型的快速草圖。
店面a one_of<int, double, std::string, char>
作爲您的T
。通過apply
傳遞一個覆蓋每個函數的函數或get<T>
。
上面是C++ 14,因爲它使它更容易。它不包括具有返回值的apply
,因爲它使得它更容易。兩者都可以彌補,但它需要工作,而且真的,你應該看看如何boost
而不是使用上述。
什麼是'矢量'的模板參數中的'int'應該是?你需要一個[Boost.Variants]的矢量(http://www.boost.org/doc/libs/release/doc/html/variant.html)。 – Praetorian
糟糕,我犯了一個錯誤!它應該只是'std :: vector> params;' –
所以,'boost :: variant'會解決你的問題嗎?您也可以編寫自己的類型安全標籤的聯合。另一個問題是,你打算如何使用這個向量的地圖'T'? – Yakk