@@ -126,19 +126,39 @@ template<typename T, traits::IsResultError... Errs>
126126 requires (sizeof ...(Errs) > 0 )
127127class Result ;
128128
129+ namespace traits {
130+
129131/* *
130132 * @brief Type trait to check if a type is a Result.
131133 * @tparam T Type to check.
132134 */
133135template <typename >
134136struct is_result : std::false_type {};
135137
138+ /* *
139+ * @brief Type trait to check if a type is a Result.
140+ * @tparam T Type to check.
141+ */
136142template <typename T, typename ... Errs>
137143struct is_result <Result<T, Errs...>> : std::true_type {};
138144
145+ /* *
146+ * @brief Check whether a type is a Result
147+ * @tparam T Type to check
148+ */
139149template <typename T>
140150inline constexpr bool is_result_v = is_result<T>::value;
141151
152+ /* *
153+ * @brief Concept to check if a type is a Result
154+ *
155+ * @tparam T
156+ */
157+ template <typename T>
158+ concept IsResult = is_result_v<T>;
159+
160+ } // namespace traits
161+
142162/* *
143163 * @brief Result class for expected value or error handling (similar to std::expected).
144164 * @tparam T Type of the expected value.
@@ -255,174 +275,6 @@ class Result {
255275 return !std::holds_alternative<std::monostate>(m_error);
256276 }
257277
258- // and_then: lvalue
259- template <typename Fn>
260- auto and_then (Fn&& f) & {
261- using ResultType = std::invoke_result_t <Fn, T>;
262- static_assert (is_result_v<ResultType>, " Fn must return a Result type" );
263-
264- if (has_error ()) {
265- return std::visit ([](auto && err) -> ResultType {
266- return ResultType (std::forward<decltype (err)>(err));
267- }, m_error);
268- } else {
269- return f (m_value);
270- }
271- }
272-
273- // and_then: const lvalue
274- template <typename Fn>
275- auto and_then (Fn&& f) const & {
276- using ResultType = std::invoke_result_t <Fn, const T&>;
277- static_assert (is_result_v<ResultType>, " Fn must return a Result type" );
278-
279- if (has_error ()) {
280- return std::visit ([](auto && err) -> ResultType {
281- return ResultType (std::forward<decltype (err)>(err));
282- }, m_error);
283- } else {
284- return f (m_value);
285- }
286- }
287-
288- // and_then: rvalue
289- template <typename Fn>
290- auto and_then (Fn&& f) && {
291- using ResultType = std::invoke_result_t <Fn, T&&>;
292- static_assert (is_result_v<ResultType>, " Fn must return a Result type" );
293-
294- if (has_error ()) {
295- return std::visit ([](auto && err) -> ResultType {
296- return ResultType (std::forward<decltype (err)>(err));
297- }, std::move (m_error));
298- } else {
299- return f (std::move (m_value));
300- }
301- }
302-
303- // and_then: const rvalue
304- template <typename Fn>
305- auto and_then (Fn&& f) const && {
306- using ResultType = std::invoke_result_t <Fn, const T&&>;
307- static_assert (is_result_v<ResultType>, " Fn must return a Result type" );
308-
309- if (has_error ()) {
310- return std::visit ([](auto && err) -> ResultType {
311- return ResultType (std::forward<decltype (err)>(err));
312- }, std::move (m_error));
313- } else {
314- return f (std::move (m_value));
315- }
316- }
317-
318- // or_else: lvalue
319- template <typename Fn>
320- auto or_else (Fn&& f) & {
321- if (!has_error ()) {
322- return *this ;
323- }
324-
325- return std::visit ([&f](auto && err) {
326- return f (std::forward<decltype (err)>(err));
327- }, m_error);
328- }
329-
330- // or_else: const lvalue
331- template <typename Fn>
332- auto or_else (Fn&& f) const & {
333- if (!has_error ()) {
334- return *this ;
335- }
336-
337- return std::visit ([&f](auto && err) {
338- return f (std::forward<decltype (err)>(err));
339- }, m_error);
340- }
341-
342- // or_else: rvalue
343- template <typename Fn>
344- auto or_else (Fn&& f) && {
345- if (!has_error ()) {
346- return std::move (*this );
347- }
348-
349- return std::visit ([&f](auto && err) {
350- return f (std::forward<decltype (err)>(err));
351- }, std::move (m_error));
352- }
353-
354- // or_else: const rvalue
355- template <typename Fn>
356- auto or_else (Fn&& f) const && {
357- if (!has_error ()) {
358- return std::move (*this );
359- }
360-
361- return std::visit ([&f](auto && err) {
362- return f (std::forward<decltype (err)>(err));
363- }, std::move (m_error));
364- }
365-
366- // transform: lvalue
367- template <typename Fn>
368- auto transform (Fn&& f) & {
369- using U = std::invoke_result_t <Fn, T>;
370- using ResultType = Result<U, Errs...>;
371-
372- if (has_error ()) {
373- return std::visit ([](auto && err) -> ResultType {
374- return ResultType (std::forward<decltype (err)>(err));
375- }, m_error);
376- } else {
377- return ResultType (f (m_value));
378- }
379- }
380-
381- // transform: const lvalue
382- template <typename Fn>
383- auto transform (Fn&& f) const & {
384- using U = std::invoke_result_t <Fn, const T&>;
385- using ResultType = Result<U, Errs...>;
386-
387- if (has_error ()) {
388- return std::visit ([](auto && err) -> ResultType {
389- return ResultType (std::forward<decltype (err)>(err));
390- }, m_error);
391- } else {
392- return ResultType (f (m_value));
393- }
394- }
395-
396- // transform: rvalue
397- template <typename Fn>
398- auto transform (Fn&& f) && {
399- using U = std::invoke_result_t <Fn, T&&>;
400- using ResultType = Result<U, Errs...>;
401-
402- if (has_error ()) {
403- return std::visit ([](auto && err) -> ResultType {
404- return ResultType (std::forward<decltype (err)>(err));
405- }, std::move (m_error));
406- } else {
407- return ResultType (f (std::move (m_value)));
408- }
409- }
410-
411- // transform: const rvalue
412- template <typename Fn>
413- auto transform (Fn&& f) const && {
414- using U = std::invoke_result_t <Fn, const T&&>;
415- using ResultType = Result<U, Errs...>;
416-
417- if (has_error ()) {
418- return std::visit ([](auto && err) -> ResultType {
419- return ResultType (std::forward<decltype (err)>(err));
420- }, std::move (m_error));
421- } else {
422- return ResultType (f (std::move (m_value)));
423- }
424- }
425-
426278 constexpr operator T&() & {
427279 return m_value;
428280 }
@@ -537,174 +389,6 @@ class Result<void, Errs...> {
537389 return !std::holds_alternative<std::monostate>(m_error);
538390 }
539391
540- // and_then: lvalue
541- template <typename Fn>
542- auto and_then (Fn&& f) & {
543- using ResultType = std::invoke_result_t <Fn>;
544- static_assert (is_result_v<ResultType>, " Fn must return a Result type" );
545-
546- if (has_error ()) {
547- return std::visit ([](auto && err) -> ResultType {
548- return ResultType (std::forward<decltype (err)>(err));
549- }, m_error);
550- } else {
551- return f ();
552- }
553- }
554-
555- // and_then: const lvalue
556- template <typename Fn>
557- auto and_then (Fn&& f) const & {
558- using ResultType = std::invoke_result_t <Fn>;
559- static_assert (is_result_v<ResultType>, " Fn must return a Result type" );
560-
561- if (has_error ()) {
562- return std::visit ([](auto && err) -> ResultType {
563- return ResultType (std::forward<decltype (err)>(err));
564- }, m_error);
565- } else {
566- return f ();
567- }
568- }
569-
570- // and_then: rvalue
571- template <typename Fn>
572- auto and_then (Fn&& f) && {
573- using ResultType = std::invoke_result_t <Fn>;
574- static_assert (is_result_v<ResultType>, " Fn must return a Result type" );
575-
576- if (has_error ()) {
577- return std::visit ([](auto && err) -> ResultType {
578- return ResultType (std::forward<decltype (err)>(err));
579- }, std::move (m_error));
580- } else {
581- return f ();
582- }
583- }
584-
585- // and_then: const rvalue
586- template <typename Fn>
587- auto and_then (Fn&& f) const && {
588- using ResultType = std::invoke_result_t <Fn>;
589- static_assert (is_result_v<ResultType>, " Fn must return a Result type" );
590-
591- if (has_error ()) {
592- return std::visit ([](auto && err) -> ResultType {
593- return ResultType (std::forward<decltype (err)>(err));
594- }, std::move (m_error));
595- } else {
596- return f ();
597- }
598- }
599-
600- // or_else: lvalue
601- template <typename Fn>
602- auto or_else (Fn&& f) & {
603- if (!has_error ()) {
604- return *this ;
605- }
606-
607- return std::visit ([&f](auto && err) {
608- return f (std::forward<decltype (err)>(err));
609- }, m_error);
610- }
611-
612- // or_else: const lvalue
613- template <typename Fn>
614- auto or_else (Fn&& f) const & {
615- if (!has_error ()) {
616- return *this ;
617- }
618-
619- return std::visit ([&f](auto && err) {
620- return f (std::forward<decltype (err)>(err));
621- }, m_error);
622- }
623-
624- // or_else: rvalue
625- template <typename Fn>
626- auto or_else (Fn&& f) && {
627- if (!has_error ()) {
628- return std::move (*this );
629- }
630-
631- return std::visit ([&f](auto && err) {
632- return f (std::forward<decltype (err)>(err));
633- }, std::move (m_error));
634- }
635-
636- // or_else: const rvalue
637- template <typename Fn>
638- auto or_else (Fn&& f) const && {
639- if (!has_error ()) {
640- return std::move (*this );
641- }
642-
643- return std::visit ([&f](auto && err) {
644- return f (std::forward<decltype (err)>(err));
645- }, std::move (m_error));
646- }
647-
648- // transform: lvalue
649- template <typename Fn>
650- auto transform (Fn&& f) & {
651- using U = std::invoke_result_t <Fn>;
652- using ResultType = Result<U, Errs...>;
653-
654- if (has_error ()) {
655- return std::visit ([](auto && err) -> ResultType {
656- return ResultType (std::forward<decltype (err)>(err));
657- }, m_error);
658- } else {
659- return ResultType (f ());
660- }
661- }
662-
663- // transform: const lvalue
664- template <typename Fn>
665- auto transform (Fn&& f) const & {
666- using U = std::invoke_result_t <Fn>;
667- using ResultType = Result<U, Errs...>;
668-
669- if (has_error ()) {
670- return std::visit ([](auto && err) -> ResultType {
671- return ResultType (std::forward<decltype (err)>(err));
672- }, m_error);
673- } else {
674- return ResultType (f ());
675- }
676- }
677-
678- // transform: rvalue
679- template <typename Fn>
680- auto transform (Fn&& f) && {
681- using U = std::invoke_result_t <Fn>;
682- using ResultType = Result<U, Errs...>;
683-
684- if (has_error ()) {
685- return std::visit ([](auto && err) -> ResultType {
686- return ResultType (std::forward<decltype (err)>(err));
687- }, std::move (m_error));
688- } else {
689- return ResultType (f ());
690- }
691- }
692-
693- // transform: const rvalue
694- template <typename Fn>
695- auto transform (Fn&& f) const && {
696- using U = std::invoke_result_t <Fn>;
697- using ResultType = Result<U, Errs...>;
698-
699- if (has_error ()) {
700- return std::visit ([](auto && err) -> ResultType {
701- return ResultType (std::forward<decltype (err)>(err));
702- }, std::move (m_error));
703- } else {
704- return ResultType (f ());
705- }
706- }
707-
708392 private:
709393 // instead of wrapping the variant in std::optional, we can use std::monostate
710394 std::variant<std::monostate, Errs...> m_error; // /< Variant holding an error or monostate.
0 commit comments