-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathvisit.h
More file actions
79 lines (66 loc) · 3.14 KB
/
visit.h
File metadata and controls
79 lines (66 loc) · 3.14 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
#pragma once
#include "helper_classes.h"
#include <array>
#include <functional>
#include <type_traits>
#include <utility>
template <typename Visitor, typename... Variants, std::size_t... Indexes>
constexpr auto get_matrix_impl(std::index_sequence<Indexes...>) noexcept {
struct dispatcher {
static constexpr decltype(auto) dispatch(Visitor&& v, Variants&&... var) {
return (std::forward<Visitor>(v))(get<Indexes>(std::forward<Variants>(var))...);
}
};
return &dispatcher::dispatch;
}
template <typename Visitor, typename... Variants, std::size_t... IS, std::size_t... JS, typename... LS>
constexpr auto get_matrix_impl(std::index_sequence<IS...>, std::index_sequence<JS...>, LS... ls) noexcept {
return std::array{get_matrix_impl<Visitor, Variants...>(std::index_sequence<IS..., JS>(), ls...)...};
}
template <typename Visitor, typename... Variants>
constexpr auto get_matrix() noexcept {
return get_matrix_impl<Visitor, Variants...>(std::index_sequence<>(),
std::make_index_sequence<variant_size_v<std::decay_t<Variants>>>()...);
}
template <typename Visitor, typename Variant, std::size_t Index>
constexpr auto get_array_impl_impl(std::index_sequence<Index>) noexcept {
struct dispatcher {
static constexpr decltype(auto) dispatch(Visitor&& v, Variant&& var) {
return std::forward<Visitor>(v)(in_place_index<Index>, std::forward<Variant>(var));
}
};
return &dispatcher::dispatch;
}
template <typename Visitor, typename Variant, std::size_t... Indexes>
constexpr auto get_array_impl(std::index_sequence<Indexes...>) noexcept {
return std::array{get_array_impl_impl<Visitor, Variant>(std::index_sequence<Indexes>())...};
}
template <typename Visitor, typename Variant>
constexpr auto get_array() noexcept {
return get_array_impl<Visitor, Variant>(std::make_index_sequence<variant_size_v<std::decay_t<Variant>>>());
}
template <typename F>
constexpr decltype(auto) at(F&& func) {
return std::forward<F>(func);
}
template <typename Matrix, typename... Indexes>
constexpr decltype(auto) at(Matrix&& matrix, std::size_t index, Indexes... others) {
return at(std::forward<Matrix>(matrix)[index], others...);
}
template <typename Visitor, typename Variant>
inline constexpr auto visit_by_index_array = get_array<Visitor, Variant>();
template <typename Visitor, typename Variant>
constexpr decltype(auto) visit_by_index(Visitor&& visitor, Variant&& variant) {
return at(visit_by_index_array<Visitor, Variant>, variant.index())(std::forward<Visitor>(visitor),
std::forward<Variant>(variant));
}
template <typename Visitor, typename... Variants>
inline constexpr auto visit_matrix = get_matrix<Visitor, Variants...>();
template <typename Visitor, typename... Variants>
constexpr decltype(auto) visit(Visitor&& visitor, Variants&&... variants) {
if ((variants.valueless_by_exception() || ...)) {
throw bad_variant_access();
}
return at(visit_matrix<Visitor, Variants...>, variants.index()...)(std::forward<Visitor>(visitor),
std::forward<Variants>(variants)...);
}