Вы не можете.
Boost :: Вариант и STD :: Вариант решения этой проблемы, так что объединение несет в себе информацию о типе вам нужно.
Вы можете создать необработанный союз следующим образом:
template<class T>
struct data_holder {
T data;
};
template<class...Ts>
struct union_data;
template<>
struct union_data<>{};
template<class T0>
struct union_data<T0>:data_holder<T0> {};
template<class T0, class...Ts>
struct union_data<T0, Ts...> {
union {
union_data<T0> lhs;
union_data<Ts...> rhs;
};
};
template<class...Ts>
struct raw_union:union_data<Ts...>{
template<class T>
constexpr static bool valid_type() {
return (std::is_same<T, Ts>{}||...); // rewrite in C++14/11
}
template<class T>
union_data<T>* get_data_ptr() {
static_assert( valid_type<T>() );
return reinterpret_cast<union_data<T>*>(this);
}
template<class T>
union_data<T> const* get_data_ptr() const{
static_assert( valid_type<T>() );
return reinterpret_cast<union_data<T> const*>(this);
}
template<class T>
T& get_unsafe() {
return get_data_ptr<T>()->data;
}
template<class T>
T const& get_unsafe() const {
return get_data_ptr<T>()->data;
}
template<class T, class...Us>
T& emplace( Us&&... us ) {
auto* ptr = ::new( (void*)get_data_ptr<T>() ) union_data<T>{ T(std::forward<Us>(us)...) };
return ptr->data;
}
template<class T>
void dtor() {
get_data_ptr<T>()->~T();
}
};
, который небезопасен и недискриминационный, но проверяет, действительно ли foo.get_unsafe<int>()
содержит int
.
живой пример .
Использование:
raw_union<int, double> un;
un.emplace<int>(7);
std::cout << un.get_unsafe<int>() << "\n";
не поддерживает несколько членов объединения одного типа. Вы отвечаете за вызов .emplace<T>(x)
перед использованием T
, и если нетривиальный деструктор .dtor<T>()
.
Доступ к неактивным членам так же опасен, как и для необработанных объединений C / C ++.