32#ifndef KBLIB_VARIANT_H
33#define KBLIB_VARIANT_H
50template <
typename T,
typename =
void>
53constexpr inline bool is_variant_like_v<T, void_t<std::variant_size<T>>> =
true;
66template <
typename To,
typename... Ts>
68 const std::variant<Ts...>& v) -> To {
69 return std::visit([](
const auto& t) -> To {
return lexical_cast<To>(t); },
79template <
typename To,
typename... Ts>
81 return std::visit([](
const auto& t) -> To {
return static_cast<To
>(t); }, v);
90template <
typename To,
typename... Ts>
92 return std::visit([](
const auto& t) {
return lexical_cast<To>(t); }, v);
101template <
typename... Ts>
103 using Ts::operator()...;
105template <
typename... Ts>
114 template <
typename T>
125 template <
typename... Ts>
130 using type = std::tuple<Ts...>;
135 template <
typename T>
142 template <
typename Variant,
typename F, std::size_t... Is>
144 return std::array{+[](Variant&& variant, F&& f) ->
decltype(
auto) {
145 return std::forward<F>(f)(
147 std::get<Is>(std::forward<Variant>(variant)));
153inline namespace literals {
155 template <
char... Cs>
157 constexpr char arr[] = {Cs...};
158 return std::in_place_index_t<parse_integer<std::size_t>(arr)>{};
175template <
typename Variant,
typename... Fs>
176constexpr auto visit_indexed(Variant&& variant, Fs&&... fs) ->
decltype(
auto) {
177 if (variant.valueless_by_exception()) {
178 throw std::bad_variant_access();
180 using visitor_t =
decltype(
visitor{std::forward<Fs>(fs)...});
181 return detail::indexed_visitor_impl<Variant, visitor_t>(
182 std::make_index_sequence<
183 std::variant_size_v<std::decay_t<Variant>>>())[variant.index()](
184 std::forward<Variant>(variant),
visitor{std::forward<Fs>(fs)...});
193template <
typename To,
typename From>
195 static_assert(contains_types_v<detail::tuple_type_t<std::decay_t<To>>,
197 "To must include all types in From");
200 return To(std::in_place_type<
201 std::variant_alternative_t<
constant, std::decay_t<From>>>,
202 std::forward<
decltype(x)>(x));
220template <
typename V,
typename F,
typename... Fs>
229 template <
typename F,
typename... Ts>
233 template <
typename Callable,
typename Variant>
236 template <
typename F,
typename... Ts>
240 template <
typename F,
typename... Ts>
244 template <
typename F,
typename... Ts>
248 template <
typename F,
typename... Ts>
252 template <
typename F,
typename... Ts>
256 template <
typename F,
typename... Ts>
260 template <
typename V,
typename F, std::size_t I, std::size_t... Is>
262 V&& v, F&& f, std::index_sequence<I, Is...>) {
263 static_assert(I < std::variant_size_v<std::decay_t<V>>);
264 if (
auto* p = std::get_if<I>(&v)) {
265 return std::forward<F>(f)(
266 static_cast<decltype(std::get<I>(std::forward<V>(v)))
>(*p));
267 }
else if constexpr (
sizeof...(Is) > 0) {
268 return visit_impl(std::forward<V>(v), std::forward<F>(f),
269 std::index_sequence<Is...>{});
271 throw std::bad_variant_access();
275 template <
typename V,
typename F, std::size_t I, std::size_t... Is>
277 V&& v, F&& f, std::index_sequence<I, Is...>) {
278 static_assert(I < std::variant_size_v<std::decay_t<V>>);
279 if (
auto* p = std::get_if<I>(&v)) {
281 static_cast<decltype(std::get<I>(std::forward<V>(v)))
>(*p));
283 }
else if constexpr (
sizeof...(Is) > 0) {
285 std::index_sequence<Is...>{});
294template <
typename V,
typename F,
typename... Fs>
295[[gnu::always_inline]]
constexpr auto visit2(V&& v, F&& f, Fs&&... fs)
297 auto visitor_obj =
visitor{std::forward<F>(f), std::forward<Fs>(fs)...};
299 "Some variant types not accepted by any visitors.");
301 std::forward<V>(v), std::move(visitor_obj),
302 std::make_index_sequence<std::variant_size_v<std::decay_t<V>>>{});
305template <
typename V,
typename F,
typename... Fs>
306[[gnu::always_inline]]
constexpr auto visit2_nop(V&& v, F&& f, Fs&&... fs)
308 auto visitor_obj =
visitor{std::forward<F>(f), std::forward<Fs>(fs)...};
310 "Some variant types not accepted by any visitors.");
312 std::forward<V>(v), visitor_obj,
313 std::make_index_sequence<std::variant_size_v<std::decay_t<V>>>{});
333 return [&v](
auto... fs) ->
decltype(
auto) {
334 return kblib::visit(v, std::forward<
decltype(fs)>(fs)...);
Provides facilities to convert between various kinds of representations.
Provides basic compile-time logic operations.
constexpr bool invocable_with_all_v
constexpr auto indexed_visitor_impl(std::index_sequence< Is... >) -> auto
Generates an array of function pointers which will unwrap the variant and pass the index to the funct...
typename tuple_type< T >::type tuple_type_t
constexpr decltype(auto) visit_impl(V &&v, F &&f, std::index_sequence< I, Is... >)
constexpr void visit_nop_impl(V &&v, F &&f, std::index_sequence< I, Is... >)
constexpr bool v_invocable_with_all_v
auto static_coerce(const std::variant< Ts... > &v) -> To
static_casts the value of v (no matter its type) to type To.
typename ignore< U, T >::type ignore_t
An alias for ignore<U, T>::type.
auto coerce(const std::variant< Ts... > &v) -> To
Lexically converts the value of v (no matter its type) to type To.
constexpr bool is_variant_like_v
constexpr auto visit_indexed(Variant &&variant, Fs &&... fs) -> decltype(auto)
Visit a variant, but pass the index (as an integral_constant) to the visitor. This allows for a visit...
constexpr auto visit2_nop(V &&v, F &&f, Fs &&... fs) -> void
visitor(Ts...) -> visitor< Ts... >
constexpr auto variant_cast(From &&v) -> To
Promotes an input variant to a super-variant. That is, one which provides at least the same set of ty...
std::integral_constant< bool, v > bool_constant
constexpr auto visit(V &v) -> auto
Two-step visiting interface. Takes a variant, and returns an object which can be called with any numb...
constexpr auto visit2(V &&v, F &&f, Fs &&... fs) -> decltype(auto)
auto lexical_coerce(const std::variant< Ts... > &v) -> To
Lexically converts the value of v (no matter its type) to type To.
constexpr auto visit(V &&v, F &&f, Fs &&... fs) -> decltype(auto)
Wraps std::visit to provide an interface taking one variant and any number of functors providing an o...
std::tuple< Ts... > type
A tuple of the same types as T is a variant of.
Given a std::variant T, provides the member type which is a tuple of the same types.
std::tuple<> type
Non-variant inputs produce the empty tuple.
Helper class for std::visiting a std::variant.
Provides macros and basic templates used by the rest of kblib.
#define KBLIB_NODISCARD
This internal macro is used to provide a fallback for [[nodiscard]] in C++14.