16 #ifndef SUMTY_ERROR_SET_HPP
17 #define SUMTY_ERROR_SET_HPP
19 #include "sumty/detail/fwd.hpp"
20 #include "sumty/detail/traits.hpp"
21 #include "sumty/detail/utils.hpp"
22 #include "sumty/utils.hpp"
23 #include "sumty/variant.hpp"
26 #include <initializer_list>
27 #include <type_traits>
117 template <
typename... T>
118 class error_set : variant<T...> {
120 static_assert(detail::all_unique_v<T...>,
121 "All error types in an error_set must be unqiue");
123 [[nodiscard]]
constexpr variant<T...>& set_() &
noexcept {
124 return *
static_cast<variant<T...>*>(
this);
127 [[nodiscard]]
constexpr const variant<T...>& set_()
const&
noexcept {
128 return *
static_cast<
const variant<T...>*>(
this);
131 [[nodiscard]]
constexpr variant<T...>&& set_() && {
132 return std::move(*
static_cast<variant<T...>*>(
this));
135 [[nodiscard]]
constexpr const variant<T...>&& set_()
const&& {
136 return std::move(*
static_cast<
const variant<T...>*>(
this));
139 template <
typename...>
140 friend class error_set;
167 CONDITIONALLY_NOEXCEPT;
198 CONDITIONALLY_NOEXCEPT;
234 CONDITIONALLY_NOEXCEPT;
262 template <size_t IDX,
typename... Args>
264 explicit(
sizeof...(
Args) == 0)
269 constexpr error_set(std::in_place_index_t<IDX> inplace, Args&&... args)
270 : variant<T...>(inplace, std::forward<Args>(args)...) {
301 template <size_t IDX,
typename U,
typename... Args>
303 std::initializer_list<U> init,
305 : variant<T...>(inplace, init, std::forward<Args>(args)...) {}
327 template <
typename U,
typename... Args>
329 explicit(
sizeof...(
Args) == 0)
336 : variant<T...>(inplace, std::forward<Args>(args)...) {
359 template <
typename U,
typename V,
typename... Args>
361 std::initializer_list<V> init,
363 : variant<T...>(inplace, init, std::forward<Args>(args)...) {}
389 template <
typename U>
399 : variant<T...>(std::forward<U>(value)) {
427 template <
typename U>
435 : variant<T...>(init) {
463 template <
typename... U>
469 constexpr error_set(
const error_set<U...>& other) : variant<T...>(detail::uninit) {
470 other.set_().visit_informed([
this](
const auto& value,
auto info) {
472 .
template uninit_emplace<
473 detail::index_of_v<
typename decltype(info)::type, T...>>(value);
502 template <
typename... U>
509 constexpr error_set(error_set<U...>&& other) : variant<T...>(detail::uninit) {
511 std::move(other.set_()).visit_informed([
this](
auto&& value,
auto info) {
513 .
template uninit_emplace<
514 detail::index_of_v<
typename decltype(info)::type, T...>>(
515 info.forward(value));
531 CONDITIONALLY_NOEXCEPT;
569 CONDITIONALLY_NOEXCEPT;
613 CONDITIONALLY_NOEXCEPT;
640 template <
typename U>
646 set_() = std::forward<U>(rhs);
676 template <
typename U>
680 constexpr error_set&
operator=(std::initializer_list<U> rhs) {
706 template <
typename... U>
711 constexpr error_set&
operator=(
const error_set<U...>& rhs) {
712 rhs.set_().visit_informed([
this](
auto&& value,
auto info) {
714 .
template emplace<detail::index_of_v<
typename decltype(info)::type, T...>>(
741 template <
typename... U>
747 constexpr error_set&
operator=(error_set<U...>&& rhs) {
748 std::move(rhs.set_()).visit_informed([
this](
auto&& value,
auto info) {
750 .
template emplace<detail::index_of_v<
typename decltype(info)::type, T...>>(
751 info.forward(value));
777 [[nodiscard]]
constexpr size_t
index()
const noexcept {
return set_().index(); }
801 template <size_t I,
typename... Args>
804 typename detail::traits<detail::select_t<I, T...>>::
reference
809 return set_().
template emplace<I>(std::forward<Args>(args)...);
835 template <size_t I,
typename U,
typename... Args>
838 typename detail::traits<detail::select_t<I, T...>>::
reference
842 emplace(std::initializer_list<U> ilist, Args&&... args) {
843 return set_().
template emplace<I>(ilist, std::forward<Args>(args)...);
868 template <
typename U,
typename... Args>
876 return set_().
template emplace<U>(std::forward<Args>(args)...);
902 template <
typename U,
typename V,
typename... Args>
909 emplace(std::initializer_list<V> ilist, Args&&... args) {
910 return set_().
template emplace<U>(ilist, std::forward<Args>(args)...);
939 [[nodiscard]]
constexpr
941 typename detail::traits<detail::select_t<I, T...>>::
reference
946 return set_()[index];
972 [[nodiscard]]
constexpr
979 return set_()[index];
1004 [[nodiscard]]
constexpr
1011 return std::move(set_())[index];
1037 [[nodiscard]]
constexpr
1044 return std::move(set_())[index];
1072 template <
typename U>
1073 [[nodiscard]]
constexpr
1080 return set_()[type];
1104 template <
typename U>
1105 [[nodiscard]]
constexpr
1112 return set_()[type];
1136 template <
typename U>
1137 [[nodiscard]]
constexpr
1144 return std::move(set_())[type];
1168 template <
typename U>
1169 [[nodiscard]]
constexpr
1176 return std::move(set_())[type];
1204 [[nodiscard]]
constexpr
1206 typename detail::traits<detail::select_t<I, T...>>::
reference
1211 return set_().
template get<I>();
1235 [[nodiscard]]
constexpr
1242 return set_().
template get<I>();
1266 [[nodiscard]]
constexpr
1273 return std::move(set_()).
template get<I>();
1297 [[nodiscard]]
constexpr
1304 return std::move(set_()).
template get<I>();
1331 template <
typename U>
1332 [[nodiscard]]
constexpr
1339 return set_().
template get<U>();
1362 template <
typename U>
1363 [[nodiscard]]
constexpr
1370 return set_().
template get<U>();
1393 template <
typename U>
1394 [[nodiscard]]
constexpr
1401 return std::move(set_()).
template get<U>();
1424 template <
typename U>
1425 [[nodiscard]]
constexpr
1432 return std::move(set_()).
template get<U>();
1457 [[nodiscard]]
constexpr
1459 typename detail::traits<detail::select_t<I, T...>>::
pointer
1464 return set_().
template get_if<I>();
1489 [[nodiscard]]
constexpr
1491 typename detail::traits<detail::select_t<I, T...>>::
const_pointer
1496 return set_().
template get_if<I>();
1520 template <
typename U>
1524 [[nodiscard]]
constexpr
1526 typename detail::traits<U>::
pointer
1531 return set_().
template get_if<U>();
1555 template <
typename U>
1556 [[nodiscard]]
constexpr
1563 return set_().
template get_if<U>();
1584 template <
typename U>
1586 return set_().
template holds_alternative<U>();
1619 template <
typename V>
1622 detail::invoke_result_t<
1624 typename detail::traits<detail::select_t<0, T...>>::
reference>
1629 return set_().visit(std::forward<V>(visitor));
1662 template <
typename V>
1665 detail::invoke_result_t<
1672 return set_().visit(std::forward<V>(visitor));
1705 template <
typename V>
1708 detail::invoke_result_t<
1715 return std::move(set_()).visit(std::forward<V>(visitor));
1748 template <
typename V>
1751 detail::invoke_result_t<
1758 return std::move(set_()).visit(std::forward<V>(visitor));
1815 template <
typename V>
1818 detail::invoke_result_t<
1820 typename detail::traits<detail::select_t<0, T...>>::
reference,
1821 detail::alternative_info<0, variant<T...>>>
1826 return set_().visit_informed(std::forward<V>(visitor));
1883 template <
typename V>
1886 detail::invoke_result_t<
1889 detail::alternative_info<0, variant<T...>>>
1894 return set_().visit_informed(std::forward<V>(visitor));
1951 template <
typename V>
1954 detail::invoke_result_t<
1957 detail::alternative_info<0, variant<T...>>>
1962 return std::move(set_()).visit_informed(std::forward<V>(visitor));
2019 template <
typename V>
2022 detail::invoke_result_t<
2025 detail::alternative_info<0, variant<T...>>>
2030 return std::move(set_()).visit_informed(std::forward<V>(visitor));
2055 constexpr void swap(error_set& other)
2062 set_().swap(other.set_());
2085 template <
typename T,
typename... U>
2087 return e.
template holds_alternative<T>();
2115 template <size_t I,
typename... T>
2118 typename detail::traits<detail::select_t<I, T...>>::
reference
2123 return e.
template get<I>();
2147 template <size_t I,
typename... T>
2154 get(
const error_set<T...>& e) {
2155 return e.
template get<I>();
2179 template <size_t I,
typename... T>
2187 return std::move(e).
template get<I>();
2211 template <size_t I,
typename... T>
2218 get(
const error_set<T...>&& e) {
2219 return std::move(e).
template get<I>();
2247 template <
typename T,
typename... U>
2255 return e.
template get<T>();
2279 template <
typename T,
typename... U>
2286 get(
const error_set<U...>& e) {
2287 return e.
template get<T>();
2311 template <
typename T,
typename... U>
2319 return std::move(e).
template get<T>();
2343 template <
typename T,
typename... U>
2350 get(
const error_set<U...>&& e) {
2351 return std::move(e).
template get<T>();
2376 template <size_t I,
typename... T>
2379 typename detail::traits<detail::select_t<I, T...>>::
pointer
2384 return e.
template get_if<I>();
2409 template <size_t I,
typename... T>
2412 typename detail::traits<detail::select_t<I, T...>>::
const_pointer
2417 return e.
template get_if<I>();
2442 template <
typename T,
typename... U>
2445 typename detail::traits<T>::
pointer
2450 return e.
template get_if<T>();
2475 template <
typename T,
typename... U>
2483 return e.
template get_if<T>();
2509 template <
typename... T>
2510 constexpr void swap(error_set<T...>& a, error_set<T...>& b)
2512 noexcept(
noexcept(
a.
swap(
b)))
2522 template <
typename T>
2523 struct error_set_size_helper;
2525 template <
typename... T>
2526 struct error_set_size_helper<error_set<T...>>
2527 : std::integral_constant<size_t,
sizeof...(T)> {};
2529 template <
typename... T>
2530 struct error_set_size_helper<
const error_set<T...>>
2531 : std::integral_constant<size_t,
sizeof...(T)> {};
2533 template <size_t I,
typename T>
2534 struct error_set_alternative_helper;
2536 template <size_t I,
typename... T>
2537 struct error_set_alternative_helper<I, error_set<T...>> {
2538 using type = detail::select_t<I, T...>;
2541 template <size_t I,
typename... T>
2542 struct error_set_alternative_helper<I,
const error_set<T...>>
2543 : error_set_alternative_helper<I, error_set<T...>> {};
2545 template <
typename T,
typename U>
2546 struct merge_error_set_helper;
2548 template <
typename... T,
typename U>
2549 requires(all_unique_v<T..., U>)
2550 struct merge_error_set_helper<error_set<T...>, error_set<U>> {
2551 using type = error_set<T..., U>;
2554 template <
typename... T,
typename U>
2555 requires(!all_unique_v<T..., U>)
2556 struct merge_error_set_helper<error_set<T...>, error_set<U>> {
2557 using type = error_set<T...>;
2560 template <
typename... T,
typename U0,
typename... UN>
2561 requires(all_unique_v<T..., U0>)
2562 struct merge_error_set_helper<error_set<T...>, error_set<U0, UN...>>
2563 : merge_error_set_helper<error_set<T..., U0>, error_set<UN...>> {};
2565 template <
typename... T,
typename U0,
typename... UN>
2566 requires(!all_unique_v<T..., U0>)
2567 struct merge_error_set_helper<error_set<T...>, error_set<U0, UN...>>
2568 : merge_error_set_helper<error_set<T...>, error_set<UN...>> {};
2570 template <
typename T,
typename U>
2571 requires(!is_error_set_v<std::remove_cvref_t<T>> &&
2572 !is_error_set_v<std::remove_cvref_t<U>>)
2573 struct merge_error_set_helper<T, U> : merge_error_set_helper<error_set<T>, error_set<U>> {};
2575 template <
typename T,
typename U>
2576 requires(is_error_set_v<std::remove_cvref_t<T>> &&
2577 !is_error_set_v<std::remove_cvref_t<U>>)
2578 struct merge_error_set_helper<T, U> : merge_error_set_helper<T, error_set<U>> {};
2580 template <
typename T,
typename U>
2581 requires(!is_error_set_v<std::remove_cvref_t<T>> &&
2582 is_error_set_v<std::remove_cvref_t<U>>)
2583 struct merge_error_set_helper<T, U> : merge_error_set_helper<error_set<T>, U> {};
2585 template <
typename... T>
2586 struct make_error_set_helper;
2588 template <
typename... T>
2589 struct make_error_set_helper<error_set<T...>> {
2590 using type = error_set<T...>;
2593 template <
typename T>
2594 requires(!is_error_set_v<T>)
2595 struct make_error_set_helper<T> {
2596 using type = error_set<T>;
2599 template <
typename T0,
typename T1,
typename... TN>
2600 struct make_error_set_helper<T0, T1, TN...>
2601 : make_error_set_helper<
typename merge_error_set_helper<T0, T1>::type, TN...> {};
2631 template <
typename ES1,
typename ES2>
2658 template <
typename ES1,
typename ES2>
2693 template <
typename ES1,
typename ES2>
2723 template <
typename ES1,
typename ES2>
2740 template <
typename T>
2753 template <
typename T>
2756 template <
typename... T>
2759 template <
typename... T>
2760 struct variant_size<
const error_set<T...>> :
error_set_size<
const error_set<T...>> {};
2781 template <size_t I,
typename ES>
2801 template <size_t I,
typename ES>
2804 template <size_t I,
typename... T>
2808 template <size_t I,
typename... T>
2809 struct variant_alternative<I,
const error_set<T...>>
2835 template <
typename ES1,
typename ES2>
2860 template <
typename ES1,
typename ES2>
2884 template <
typename... T>
2905 template <
typename... T>
2909 template <
typename... T>
2910 requires((
true && ... && std::is_base_of_v<never, std::remove_cvref_t<T>>))
2911 class error_set<T...> :
public never {};