3#ifndef DUNE_COMMON_STD_VARIANT_HH
4#define DUNE_COMMON_STD_VARIANT_HH
5#ifdef DUNE_HAVE_CXX_VARIANT
11 using std::variant_size;
12 using std::variant_size_v;
15 using std::holds_alternative;
22#include <dune/common/hybridutilities.hh>
24#include <dune/common/typelist.hh>
35 template <
typename T,
typename... Ts>
38 template <
typename T,
typename... Ts>
39 struct index_in_pack<T, T, Ts...> : std::integral_constant<std::size_t, 0> {};
41 template <
typename T,
typename U,
typename... Ts>
42 struct index_in_pack<T, U, Ts...> : std::integral_constant<std::size_t, 1 + index_in_pack<T, Ts...>::value> {};
49 using Buffer = std::aligned_storage_t<
sizeof(T),
alignof(T)>;
55 TypeStorage() =
default;
57 TypeStorage(
const TypeStorage&) =
delete;
58 TypeStorage(TypeStorage&&) =
delete;
59 TypeStorage& operator=(
const TypeStorage&) =
delete;
60 TypeStorage& operator=(TypeStorage&&) =
delete;
62 void construct(
const T& t) {
63 ::new (&buffer_) T(t);
66 void construct(T&& t) {
67 ::new (&buffer_) T(std::move(t));
75 this->get() = std::move(t);
79 reinterpret_cast<T*
>(&buffer_)->~T();
83 return *(
reinterpret_cast<T*
>(&buffer_));
86 const auto& get()
const {
87 return *(
reinterpret_cast<const T*
>(&buffer_));
98 template<
typename... T>
104 union VariadicUnion<> {
106 void construct(Ti&&) { assert(
false); }
109 void assign(Ti&&) { assert(
false); }
111 void destruct(std::size_t) { assert(
false); };
115 template<
typename Head,
typename... Tail>
116 union VariadicUnion<Head, Tail...>
122 constexpr VariadicUnion() =
default;
124 VariadicUnion(
const VariadicUnion& other) =
delete;
125 VariadicUnion(VariadicUnion&& other) =
delete;
126 VariadicUnion& operator=(
const VariadicUnion& other) =
delete;
127 VariadicUnion& operator=(VariadicUnion&& other) =
delete;
130 void construct(
const Head& obj) {
131 new (&head_) TypeStorage<Head>;
132 head_.construct(obj);
135 void construct(Head&& obj) {
136 new (&head_) TypeStorage<Head>;
137 head_.construct(std::move(obj));
141 std::enable_if_t<not std::is_same<std::decay_t<Ti>, Head>::value,
int> = 0>
142 void construct(Ti&& obj) {
143 new (&tail_) VariadicUnion<Tail...>;
144 tail_.construct(std::forward<Ti>(obj));
151 void assign(
const Head& obj){
156 head_.assign(std::move(obj));
160 std::enable_if_t<not std::is_same<std::decay_t<Ti>, Head>::value,
int> = 0>
162 tail_.assign(std::forward<Ti>(obj));
168 void destruct(
size_t indexToReset) {
169 if (indexToReset == 0) {
174 tail_.destruct(indexToReset-1);
178 auto& getByIndex(std::integral_constant<size_t, 0>) {
182 const auto& getByIndex(std::integral_constant<size_t, 0>)
const {
187 auto& getByIndex(std::integral_constant<size_t, N>) {
188 return tail_.getByIndex(std::integral_constant<size_t, N-1>());
192 const auto& getByIndex(std::integral_constant<size_t, N>)
const {
193 return tail_.getByIndex(std::integral_constant<size_t, N-1>());
196 constexpr size_t size()
const {
197 return sizeof...(Tail)+1;
201 TypeStorage<Head> head_;
202 VariadicUnion<Tail...> tail_;
205 template<
typename...T>
210 constexpr static auto typeIndex()
212 return index_in_pack<std::decay_t<Ti>, T...>::value;
216 constexpr static auto indexRange()
221 constexpr void destructIfValid()
223 if (index_ != invalidIndex)
224 unions_.destruct(index_);
225 index_ = invalidIndex;
235 constexpr variant_() :
241 unions_.construct(
id(T0{}));
247 template<
typename Ti,
248 disableCopyMove<variant_, Ti> = 0>
249 constexpr variant_(Ti&& obj) :
250 index_(typeIndex<Ti>())
252 unions_.construct(std::forward<Ti>(obj));
256 variant_(
const variant_& other) {
257 index_ = other.index_;
258 if (index_==invalidIndex)
262 unions_.construct(other.template get<i>());
267 variant_(variant_&& other) {
268 index_ = other.index_;
269 if (index_==invalidIndex)
273 unions_.construct(std::move(other.template get<i>()));
275 other.destructIfValid();
279 variant_& operator=(
const variant_& other) {
280 if(index_ == other.index_) {
281 if (index_ != invalidIndex)
284 unions_.assign(other.template get<i>());
289 index_ = other.index_;
290 if (index_ != invalidIndex)
293 unions_.construct(other.template get<i>());
300 variant_& operator=(variant_&& other) {
301 if(index_ == other.index_) {
302 if (index_ != invalidIndex)
305 unions_.assign(std::move(other.template get<i>()));
310 index_ = other.index_;
311 if (index_ != invalidIndex)
314 unions_.construct(std::move(other.template get<i>()));
317 other.destructIfValid();
322 template<
typename Ti,
323 disableCopyMove<variant_, Ti> = 0>
324 constexpr variant_& operator=(Ti&& obj) {
325 constexpr auto newIndex = typeIndex<Ti>();
326 if (index_ == newIndex)
327 unions_.assign(std::forward<Ti>(obj));
332 unions_.construct(std::forward<Ti>(obj));
337 template<
typename Tp>
339 constexpr auto idx = typeIndex<Tp>();
346 template<
typename Tp>
347 const auto& get()
const {
348 constexpr auto idx = typeIndex<Tp>();
355 template<
typename Tp>
357 if (not holds_alternative<Tp>())
358 return (Tp*)
nullptr;
363 template<
typename Tp>
364 const Tp* get_if()
const {
365 if (not holds_alternative<Tp>())
366 return (Tp*)
nullptr;
371 template<std::
size_t N>
373 using Tp = std::decay_t<decltype(get<N>())>;
374 if (not holds_alternative<N>())
375 return (Tp*)
nullptr;
380 template<std::
size_t N>
381 const auto* get_if()
const {
382 using Tp = std::decay_t<decltype(get<N>())>;
383 if (not holds_alternative<N>())
384 return (Tp*)
nullptr;
389 template<std::
size_t N>
391 if (index_ != N || index_ == invalidIndex)
393 return unions_.template getByIndex(std::integral_constant<std::size_t, N>());
395 template<std::
size_t N>
396 const auto& get()
const {
397 if (index_ != N || index_ == invalidIndex)
399 return unions_.template getByIndex(std::integral_constant<std::size_t, N>());
402 constexpr std::size_t index() const noexcept {
406 constexpr auto size()
const {
421 decltype(
auto) visit(F&& func) {
422 auto dummyElseBranch = [&]() ->
decltype(
auto) {
return func(this->get<0>());};
423 auto indices = std::make_index_sequence<size_>{};
425 return func(this->
template get<
decltype(staticIndex)::value>());
430 decltype(
auto) visit(F&& func)
const {
431 auto dummyElseBranch = [&]() ->
decltype(
auto) {
return func(this->get<0>());};
432 auto indices = std::make_index_sequence<size_>{};
434 return func(this->
template get<
decltype(staticIndex)::value>());
439 template<
typename Tp>
440 constexpr bool holds_alternative()
const {
443 return (typeIndex<Tp>() == index_);
447 template<std::
size_t N>
448 constexpr bool holds_alternative()
const {
451 return (N == index_);
455 VariadicUnion<T...> unions_;
457 constexpr static auto size_ =
sizeof...(T);
463 template<
typename ...T>
466 template<
size_t N,
typename... T>
468 return var.template get<N>();
471 template<
size_t N,
typename... T>
472 const auto& get(
const variant<T...>& var) {
473 return var.template get<N>();
476 template<
typename F,
typename... T>
477 decltype(
auto) visit(F&& visitor, variant<T...>& var) {
478 return var.visit(std::forward<F>(visitor));
481 template<
typename F,
typename... T>
482 decltype(
auto) visit(F&& visitor,
const variant<T...>& var) {
483 return var.visit(std::forward<F>(visitor));
486 template<
typename Tp,
typename ...T>
487 auto& get(variant<T...>& var) {
488 return var.template get<Tp>();
491 template<
typename Tp,
typename ...T>
492 const auto& get(
const variant<T...>& var) {
493 return var.template get<Tp>();
496 template<
typename Tp,
typename ...T>
497 const auto* get_if(
const variant<T...>* var) {
499 return (
const Tp*)
nullptr;
500 return var->template get_if<Tp>();
503 template<
typename Tp,
typename ...T>
504 auto* get_if(variant<T...>* var) {
506 return (Tp*)
nullptr;
507 return var->template get_if<Tp>();
510 template<
size_t N,
typename ...T>
511 const auto* get_if(
const variant<T...>* var) {
512 using Tp = std::decay_t<
decltype(var->template get<N>())>;
514 return (
const Tp*)
nullptr;
515 return var->template get_if<N>();
518 template<
size_t N,
typename ...T>
519 auto* get_if(variant<T...>* var) {
520 using Tp = std::decay_t<
decltype(var->template get<N>())>;
522 return (Tp*)
nullptr;
523 return var->template get_if<N>();
526 template<
typename Tp,
typename ...T>
527 constexpr bool holds_alternative(
const variant<T...>& var) {
528 return var.template holds_alternative<Tp>();
531 template <
typename T>
532 struct variant_size {};
534 template <
typename... T>
535 struct variant_size<
variant<T...>>
536 : std::integral_constant<std::size_t, sizeof...(T)> { };
539 template <
typename T>
540 constexpr std::size_t variant_size_v = variant_size<T>::value;
550 constexpr bool operator>(monostate, monostate)
noexcept {
return false; }
551 constexpr bool operator<=(monostate, monostate)
noexcept {
return true; }
552 constexpr bool operator>=(monostate, monostate)
noexcept {
return true; }
553 constexpr bool operator==(monostate, monostate)
noexcept {
return true; }
554 constexpr bool operator!=(monostate, monostate)
noexcept {
return false; }
Base class for Dune-Exceptions.
Definition: exceptions.hh:94
A few common exception classes.
std::integral_constant< std::size_t, i > index_constant
An index constant with value i.
Definition: indices.hh:28
#define DUNE_THROW(E, m)
Definition: exceptions.hh:216
constexpr void forEach(Range &&range, F &&f)
Range based for loop.
Definition: hybridutilities.hh:267
constexpr decltype(auto) switchCases(const Cases &cases, const Value &value, Branches &&branches, ElseBranch &&elseBranch)
Switch statement.
Definition: hybridutilities.hh:460
decltype(auto) ifElse(const Condition &condition, IfFunc &&ifFunc, ElseFunc &&elseFunc)
A conditional expression.
Definition: hybridutilities.hh:355
EnableIfInterOperable< T1, T2, bool >::type operator<(const RandomAccessIteratorFacade< T1, V1, R1, D > &lhs, const RandomAccessIteratorFacade< T2, V2, R2, D > &rhs)
Comparison operator.
Definition: iteratorfacades.hh:635
EnableIfInterOperable< T1, T2, bool >::type operator>(const RandomAccessIteratorFacade< T1, V1, R1, D > &lhs, const RandomAccessIteratorFacade< T2, V2, R2, D > &rhs)
Comparison operator.
Definition: iteratorfacades.hh:681
EnableIfInterOperable< T1, T2, bool >::type operator==(const ForwardIteratorFacade< T1, V1, R1, D > &lhs, const ForwardIteratorFacade< T2, V2, R2, D > &rhs)
Checks for equality.
Definition: iteratorfacades.hh:235
EnableIfInterOperable< T1, T2, bool >::type operator>=(const RandomAccessIteratorFacade< T1, V1, R1, D > &lhs, const RandomAccessIteratorFacade< T2, V2, R2, D > &rhs)
Comparison operator.
Definition: iteratorfacades.hh:703
EnableIfInterOperable< T1, T2, bool >::type operator!=(const ForwardIteratorFacade< T1, V1, R1, D > &lhs, const ForwardIteratorFacade< T2, V2, R2, D > &rhs)
Checks for inequality.
Definition: iteratorfacades.hh:257
auto max(ADLTag< 0 >, const V &v1, const V &v2)
implements binary Simd::max()
Definition: defaults.hh:79
std::tuple< MetaType< T >... > TypeList
A simple type list.
Definition: typelist.hh:87
Impl::variant_< T... > variant
Incomplete re-implementation of C++17's std::variant.
Definition: variant.hh:464
Dune namespace.
Definition: alignedallocator.hh:14
void assign(T &dst, const T &src, bool mask)
masked Simd assignment (scalar version)
Definition: simd.hh:445
typename TypeListElement< i, T >::type TypeListEntry_t
Shortcut for TypeListElement<i, T>::type;.
Definition: typelist.hh:171
Utilities for reduction like operations on ranges.
Trial default constructible class.
Definition: variant.hh:547