Establish the basic functionality of the optional_variant

This commit is contained in:
Denis Blank 2018-03-08 17:26:33 +01:00
parent 22896a69af
commit e78291669c
2 changed files with 19 additions and 8 deletions

View File

@ -46,8 +46,7 @@ namespace variant {
namespace detail { namespace detail {
// We don't want to pull the algorithm header in // We don't want to pull the algorithm header in
template <typename... T> template <typename... T>
constexpr std::size_t max_size(T... i) { constexpr std::size_t max_element_of(std::initializer_list<std::size_t> list) {
constexpr std::initializer_list<std::size_t> const list{i...};
std::size_t m = 0; std::size_t m = 0;
for (auto current : list) { for (auto current : list) {
if (current > m) { if (current > m) {
@ -56,11 +55,16 @@ constexpr std::size_t max_size(T... i) {
} }
return m; return m;
} }
template <typename... T>
constexpr std::size_t storage_of_impl() {
constexpr auto size = max_element_of({sizeof(T)...});
constexpr auto align = max_element_of({alignof(T)...});
return std::aligned_storage_t<size, align>{};
}
/// Declares the aligned storage union for the given types /// Declares the aligned storage union for the given types
template <typename... T> template <typename... T>
using storage_of_t = using storage_of_t = decltype(storage_of_impl<T...>());
std::aligned_storage_t<max_size(sizeof(T)...), max_size(alignof(T)...)>;
/// The value fpr the empty slot /// The value fpr the empty slot
using slot_t = std::uint8_t; using slot_t = std::uint8_t;
@ -257,20 +261,20 @@ public:
template <typename V> template <typename V>
V& cast() noexcept { V& cast() noexcept {
assert(!is_slot(traits::index_of_t<std::decay_t<V>, T...>::value)); assert(is_slot(traits::index_of_t<std::decay_t<V>, T...>::value));
return *reinterpret_cast<std::decay_t<V>*>(&this->storage_); return *reinterpret_cast<std::decay_t<V>*>(&this->storage_);
} }
template <typename V> template <typename V>
V const& cast() const noexcept { V const& cast() const noexcept {
assert(!is_slot(traits::index_of_t<std::decay_t<V>, T...>::value)); assert(is_slot(traits::index_of_t<std::decay_t<V>, T...>::value));
return *reinterpret_cast<std::decay_t<V> const*>(&this->storage_); return *reinterpret_cast<std::decay_t<V> const*>(&this->storage_);
} }
private: private:
template <typename C, typename V> template <typename C, typename V>
static void visit_dispatch(optional_variant* me, V&& visitor) { static void visit_dispatch(optional_variant* me, V&& visitor) {
std::forward<V>(me->cast<C>()); std::forward<V>(visitor)(me->cast<C>());
} }
template <typename C, typename V> template <typename C, typename V>
static void visit_dispatch_const(optional_variant const* me, V&& visitor) { static void visit_dispatch_const(optional_variant const* me, V&& visitor) {

View File

@ -177,5 +177,12 @@ int main(int, char**) {
}); });
variant::optional_variant<int, float> v; {
variant::optional_variant<int, float> var;
var = 1;
var = 1.f;
}
int i = 0;
} }