1#ifndef PACK_ALGORITHM_HPP_
2#define PACK_ALGORITHM_HPP_
22 template<
typename... Types>
25 template<
typename Head,
typename... Tail>
26 struct AllSame<Head, Tail...>
27 : std::conjunction<std::is_same<Head, Tail>...>
35 template<
typename... Types>
36 using all_same_v = AllSame<Types...>::value;
38 template<
typename Handler,
typename... PackElements>
39 struct ValuedPackForResult
42 template<
typename Expected>
43 struct ValueTypeMapper
45 using type =
typename Expected::value_type;
48 template<
typename Expected>
49 struct ErrorTypeMapper
51 using type =
typename Expected::error_type;
54 using ResultsPack = Pack<
55 typename std::invoke_result_t<
61 using SuccessSubtypesPack = legacy::pack_map_t<
66 using ErrorSubtypesPack = legacy::pack_map_t<
71 static constexpr bool all_error_types_same =
72 rebind_pack_t<ErrorSubtypesPack, AllSame>::value;
74 static_assert(all_error_types_same,
"All error types must be equal");
76 using SuccessType = rebind_pack_t<SuccessSubtypesPack, std::tuple>;
77 using ErrorType = legacy::head_t<ErrorSubtypesPack>;
80 using type = std::expected<SuccessType, ErrorType>;
83 template<
typename Handler,
typename... PackElements>
84 using valued_pack_for_result_t =
typename ValuedPackForResult<
91 typename AccumulatedResult,
95 struct ValuedPackForUtilityResult;
99 typename AccumulatedResult,
103 struct ValuedPackForUtilityResult
112 template<
typename Expected>
113 struct ValueTypeMapper
115 using type =
typename Expected::value_type;
118 using AccumulatedResultPack =
rebind_t<
124 using NextTypesPack = Pack<
125 typename std::invoke_result_t<
131 using NextSuccessTypesPack = legacy::pack_map_t<
136 using SuccessSubtypesPack = legacy::pack_concat_t<
137 AccumulatedResultPack,
141 using SuccessType = rebind_pack_t<SuccessSubtypesPack, std::tuple>;
142 using ErrorType = ErrorType_;
145 using type = std::expected<SuccessType, ErrorType>;
150 typename AccumulatedResult,
154 using valued_pack_for_utility_result_t =
typename ValuedPackForUtilityResult<
163 typename AccumulatedResult,
166 constexpr inline std::expected<AccumulatedResult, ErrorType> valued_pack_for_utility__(
169 AccumulatedResult&& accumulated_result,
170 Unit<ErrorType> error_type
172 return std::forward<AccumulatedResult>(accumulated_result);
177 typename AccumulatedResult,
179 typename Head,
typename... Tail
181 constexpr inline valued_pack_for_utility_result_t<
186 > valued_pack_for_utility__(
187 Pack<Head, Tail...>&& pack,
189 AccumulatedResult&& accumulated_result,
190 Unit<ErrorType>&& error_type
192 auto handler_result =
193 std::invoke(handler, Unit<Head>{});
195 if (!handler_result.has_value()) [[unlikely]]
197 return std::unexpected(handler_result.error());
200 auto successful_handling_result = handler_result.value();
202 auto next_accumulated_result = std::tuple_cat(
203 std::forward<AccumulatedResult>(accumulated_result),
204 std::tuple { successful_handling_result }
207 return valued_pack_for_utility__(
209 std::forward<Handler>(handler),
210 std::move(next_accumulated_result),
211 std::move(error_type)
218template<
typename Handler,
typename... PackElements>
219constexpr implementation_details_::valued_pack_for_result_t<
220 Handler, PackElements...
227 std::forward<Handler>(handler)
230 return implementation_details_::valued_pack_for_utility__(
232 std::forward<Handler>(handler),
Compile-time type pack utilities and metaprogramming foundations.