VCCC  2024.05
VisualCamp Common C++ library
visit.hpp
Go to the documentation of this file.
1 //
2 // Created by yonggyulee on 1/31/24.
3 //
4 
5 #ifndef VCCC_VARIANT_VISIT_HPP
6 #define VCCC_VARIANT_VISIT_HPP
7 
8 #include <tuple>
9 #include <type_traits>
10 #include <utility>
11 
18 
19 namespace vccc {
20 namespace detail {
21 
22 template<std::size_t Cursor, typename R>
23 struct visitor_global {
24  template<typename T, std::size_t J, typename Vis, std::size_t... I, typename... Variants>
25  constexpr R operator()(T&&, in_place_index_t<J>, Vis&& vis, std::index_sequence<I...>, Variants&&... vars) const {
26  return visitor_global<Cursor - 1, R>{}.visit(
27  std::forward<Vis>(vis), std::index_sequence<I..., J>{}, std::forward<Variants>(vars)...);
28  }
29 
30  template<typename U, typename Vis, std::size_t... I, typename... Variants>
31  constexpr R operator()(U&&, in_place_index_t<variant_npos>, Vis&& vis, std::index_sequence<I...>, Variants&&... vars) const {
32  throw bad_variant_access{};
33  return visitor_global<Cursor - 1, R>{}.visit(
34  std::forward<Vis>(vis), std::index_sequence<I..., 0>{}, std::forward<Variants>(vars)...);
35  }
36 
37  template<typename Vis, std::size_t...I, typename... Variants>
38  constexpr R visit(Vis&& vis, std::index_sequence<I...>, Variants&&... vars) const {
39  auto&& var = std::get<Cursor - 1>(std::forward_as_tuple(std::forward<Variants>(vars)...));
40  return variant_raw_visit(
41  var.index(), std::forward<decltype(var._base().storage())>(var._base().storage()), *this,
42  std::forward<Vis>(vis), std::index_sequence<I...>{}, std::forward<Variants>(vars)...);
43  }
44 };
45 
46 template<typename R>
47 struct visitor_global<0, R> {
48  template<typename Vis, std::size_t...I, typename... Variants>
49  constexpr R visit(Vis&& vis, std::index_sequence<I...>, Variants&&... vars) const {
50  return vccc::invoke_r<R>(
51  std::forward<Vis>(vis),
52  std::forward<decltype(variant_raw_get(vars._base().storage(), in_place_index<I>))>(
53  variant_raw_get(vars._base().storage(), in_place_index<I>))...
54  );
55  }
56 };
57 
58 struct as_variant_niebloid {
59  template<typename... Ts>
60  constexpr variant<Ts...>& operator()(variant<Ts...>& var) const noexcept { return var; }
61 
62  template<typename... Ts>
63  constexpr const variant<Ts...>& operator()(const variant<Ts...>& var) const noexcept { return var;}
64 
65  template<typename... Ts>
66  constexpr variant<Ts...>&& operator()(variant<Ts...>&& var) const noexcept { return std::move(var); }
67 
68  template<typename... Ts>
69  constexpr const variant<Ts...>&& operator()(const variant<Ts...>&& var) const noexcept { return std::move(var); }
70 };
71 
72 VCCC_INLINE_OR_STATIC constexpr as_variant_niebloid as_variant{};
73 
74 template<typename Variant>
75 using as_variant_t = invoke_result_t<as_variant_niebloid, Variant>;
76 
77 template<typename Visitor, typename... Variants>
78 struct variant_visit_result {
79  using type = invoke_result_t<Visitor, decltype(get<0>(std::declval<Variants>()))...>;
80 };
81 
82 template<typename Visitor, typename... Variants>
83 using variant_visit_result_t = typename variant_visit_result<Visitor, as_variant_t<Variants>...>::type;
84 
85 } // namespace detail
86 
89 
90 template<typename R, typename Visitor, typename... Variants, std::enable_if_t<conjunction<
91  is_invocable<detail::as_variant_niebloid, Variants>...
92 >::value, int> = 0>
93 constexpr R visit(Visitor&& vis, Variants&&... vars) {
94  return detail::visitor_global<sizeof...(Variants), R>{}.visit(
95  std::forward<Visitor>(vis),
96  std::index_sequence<>{},
97  detail::as_variant(std::forward<Variants>(vars))...
98  );
99 }
100 
101 template<typename Visitor, typename... Variants, std::enable_if_t<conjunction<
102  is_invocable<detail::as_variant_niebloid, Variants>...
103 >::value, int> = 0>
104 constexpr decltype(auto)
105 visit(Visitor&& vis, Variants&&... vars) {
106  using R = detail::variant_visit_result_t<Visitor, detail::as_variant_t<Variants>...>;
107  return visit<R>(std::forward<Visitor>(vis), std::forward<Variants>(vars)...);
108 }
109 
110 namespace detail {
111 
112 
113 template<typename Visitor, typename Variant>
114 constexpr decltype(auto) visit_single(Visitor&& vis, Variant&& var) {
115  return vccc::visit(std::forward<Visitor>(vis), std::forward<Variant>(var));
116 }
117 
118 template<typename R, typename Visitor, typename Variant>
119 constexpr R visit_single(Visitor&& vis, Variant&& var) {
120  return vccc::visit<R>(std::forward<Visitor>(vis), std::forward<Variant>(var));
121 }
122 
123 } // namespace detail
124 
126 
127 } // namespace vccc
128 
129 #endif // VCCC_VARIANT_VISIT_HPP
constexpr R visit(Visitor &&vis, Variants &&... vars)
Definition: visit.hpp:93
#define VCCC_INLINE_OR_STATIC
Definition: inline_or_static.hpp:9
constexpr std::enable_if_t<(I< m *n), typename vccc::Matrix< T, m, n >::value_type & > get(vccc::Matrix< T, m, n > &matrix)
Definition: matrix.hpp:499
Definition: directory.h:12
constexpr VCCC_INLINE_OR_STATIC detail::element_niebloid< 1 > value
Definition: key_value.hpp:35