39#include <initializer_list>
45#include "pw_preprocessor/compiler.h"
46#include "pw_result/internal/result_internal.h"
47#include "pw_status/status.h"
139class Result :
private internal_result::StatusOrData<T>,
140 private internal_result::CopyCtorBase<T>,
141 private internal_result::MoveCtorBase<T>,
142 private internal_result::CopyAssignBase<T>,
143 private internal_result::MoveAssignBase<T> {
144 template <
typename U>
147 using Base = internal_result::StatusOrData<T>;
162 explicit constexpr Result();
189 std::negation<std::is_same<T, U>>,
190 std::is_constructible<T, const U&>,
191 std::is_convertible<const U&, T>,
192 std::negation<internal_result::
193 IsConstructibleOrConvertibleFromResult<T, U>>>
::
197 : Base(static_cast<const typename
Result<U>::Base&>(other)) {}
202 std::negation<std::is_same<T, U>>,
203 std::is_constructible<T, const U&>,
204 std::negation<std::is_convertible<const U&, T>>,
205 std::negation<internal_result::
206 IsConstructibleOrConvertibleFromResult<T, U>>>
::
210 : Base(static_cast<const typename
Result<U>::Base&>(other)) {}
216 std::negation<std::is_same<T, U>>,
217 std::is_constructible<T, U&&>,
218 std::is_convertible<U&&, T>,
219 std::negation<internal_result::
220 IsConstructibleOrConvertibleFromResult<T, U>>>
::
223 constexpr Result(Result<U>&& other)
224 : Base(static_cast<typename Result<U>::Base&&>(other)) {}
229 std::negation<std::is_same<T, U>>,
230 std::is_constructible<T, U&&>,
231 std::negation<std::is_convertible<U&&, T>>,
232 std::negation<internal_result::
233 IsConstructibleOrConvertibleFromResult<T, U>>>
::
236 explicit constexpr Result(Result<U>&& other)
237 : Base(static_cast<typename Result<U>::Base&&>(other)) {}
254 template <
typename U,
257 std::negation<std::is_same<T, U>>,
258 std::is_constructible<T, const U&>,
259 std::is_assignable<T, const U&>,
262 IsConstructibleOrConvertibleOrAssignableFromResult<
270 template <
typename U,
273 std::negation<std::is_same<T, U>>,
274 std::is_constructible<T, U&&>,
275 std::is_assignable<T, U&&>,
278 IsConstructibleOrConvertibleOrAssignableFromResult<
283 this->Assign(std::move(other));
303 std::is_convertible<U&&, Status>,
304 std::is_constructible<Status, U&&>,
305 std::negation<std::is_same<std::decay_t<U>, Result<T>>>,
306 std::negation<std::is_same<std::decay_t<U>, T>>,
307 std::negation<std::is_same<std::decay_t<U>, std::in_place_t>>,
308 std::negation<internal_result::
309 HasConversionOperatorToResult<T, U&&>>>
::value,
311 constexpr Result(U&& v) : Base(std::forward<U>(v)) {}
317 std::negation<std::is_convertible<U&&, Status>>,
318 std::is_constructible<Status, U&&>,
319 std::negation<std::is_same<std::decay_t<U>,
Result<T>>>,
320 std::negation<std::is_same<std::decay_t<U>, T>>,
321 std::negation<std::is_same<std::decay_t<U>, std::in_place_t>>,
322 std::negation<internal_result::
323 HasConversionOperatorToResult<T, U&&>>>
::value,
325 constexpr explicit Result(U&& v) : Base(std::forward<U>(v)) {}
331 std::is_convertible<U&&, Status>,
332 std::is_constructible<Status, U&&>,
333 std::negation<std::is_same<std::decay_t<U>, Result<T>>>,
334 std::negation<std::is_same<std::decay_t<U>, T>>,
335 std::negation<std::is_same<std::decay_t<U>, std::in_place_t>>,
336 std::negation<internal_result::
337 HasConversionOperatorToResult<T, U&&>>>
::value,
340 this->AssignStatus(std::forward<U>(v));
364 typename =
typename std::enable_if<std::conjunction<
365 std::is_constructible<T, U&&>,
366 std::is_assignable<T&, U&&>,
368 std::is_same<std::remove_cv_t<std::remove_reference_t<U>>, T>,
370 std::negation<std::is_convertible<U&&, Status>>,
372 internal_result::HasConversionOperatorToResult<T, U&&>>>>,
373 internal_result::IsForwardingAssignmentValid<T, U&&>>
::value>::type>
375 this->Assign(std::forward<U>(v));
381 template <
typename... Args>
382 explicit constexpr Result(std::in_place_t, Args&&... args);
383 template <
typename U,
typename... Args>
384 explicit constexpr Result(std::in_place_t,
385 std::initializer_list<U> ilist,
401 internal_result::IsDirectInitializationValid<T, U&&>,
402 std::is_constructible<T, U&&>,
403 std::is_convertible<U&&, T>,
405 std::is_same<std::remove_cv_t<std::remove_reference_t<U>>, T>,
407 std::negation<std::is_convertible<U&&, Status>>,
410 HasConversionOperatorToResult<T, U&&>>>>>
::value,
413 :
Result(std::in_place, std::forward<U>(u)) {}
419 internal_result::IsDirectInitializationValid<T, U&&>,
421 std::is_same<std::remove_cv_t<std::remove_reference_t<U>>, T>,
423 std::negation<std::is_constructible<Status, U&&>>,
426 HasConversionOperatorToResult<T, U&&>>>>,
427 std::is_constructible<T, U&&>,
428 std::negation<std::is_convertible<U&&, T>>>
::value,
430 explicit constexpr Result(U&& u)
431 :
Result(std::in_place, std::forward<U>(u)) {}
447 [[nodiscard]]
constexpr bool ok()
const {
return this->status_.ok(); }
521 template <typename U>
523 template <typename U>
524 constexpr T
value_or(U&& default_value) &&;
534 template <typename... Args>
538 this->MakeValue(std::forward<Args>(args)...);
540 this->MakeValue(std::forward<Args>(args)...);
550 std::is_constructible<T, std::initializer_list<U>&, Args&&...>
::value,
552 T&
emplace(std::initializer_list<U> ilist, Args&&... args) {
555 this->MakeValue(ilist, std::forward<Args>(args)...);
557 this->MakeValue(ilist, std::forward<Args>(args)...);
582 template <
typename Fn,
583 typename Ret = internal_result::InvokeResultType<Fn, T&>,
584 std::enable_if_t<std::is_copy_constructible_v<Ret>,
int> = 0>
586 static_assert(internal_result::IsResult<Ret>,
587 "Fn must return a pw::Result");
588 return ok() ? std::invoke(std::forward<Fn>(function),
value())
592 template <
typename Fn,
593 typename Ret = internal_result::InvokeResultType<Fn, T&&>,
594 std::enable_if_t<std::is_move_constructible_v<Ret>,
int> = 0>
595 constexpr auto and_then(Fn&& function) && {
596 static_assert(internal_result::IsResult<Ret>,
597 "Fn must return a pw::Result");
598 return ok() ? std::invoke(std::forward<Fn>(function), std::move(
value()))
602 template <
typename Fn,
603 typename Ret = internal_result::InvokeResultType<Fn, const T&>,
604 std::enable_if_t<std::is_copy_constructible_v<Ret>,
int> = 0>
605 constexpr auto and_then(Fn&& function)
const& {
606 static_assert(internal_result::IsResult<Ret>,
607 "Fn must return a pw::Result");
608 return ok() ? std::invoke(std::forward<Fn>(function),
value())
612 template <
typename Fn,
613 typename Ret = internal_result::InvokeResultType<Fn, const T&&>,
614 std::enable_if_t<std::is_move_constructible_v<Ret>,
int> = 0>
615 constexpr auto and_then(Fn&& function)
const&& {
616 static_assert(internal_result::IsResult<Ret>,
617 "Fn must return a pw::Result");
618 return ok() ? std::invoke(std::forward<Fn>(function), std::move(
value()))
644 template <
typename Fn,
645 typename Ret = internal_result::InvokeResultType<Fn, const Status&>,
646 std::enable_if_t<!std::is_void_v<Ret>,
int> = 0>
648 static_assert(std::is_convertible_v<Ret, Result<T>>,
649 "Fn must be convertible to a pw::Result");
650 return ok() ? *this : std::invoke(std::forward<Fn>(function),
status());
653 template <
typename Fn,
654 typename Ret = internal_result::InvokeResultType<Fn, const Status&>,
655 std::enable_if_t<std::is_void_v<Ret>,
int> = 0>
660 std::invoke(std::forward<Fn>(function),
status());
664 template <
typename Fn,
665 typename Ret = internal_result::InvokeResultType<Fn, Status&&>,
666 std::enable_if_t<!std::is_void_v<Ret>,
int> = 0>
667 constexpr Result<T>
or_else(Fn&& function) && {
668 static_assert(std::is_convertible_v<Ret, Result<T>>,
669 "Fn must be convertible to a pw::Result");
670 return ok() ? std::move(*
this)
671 : std::invoke(std::forward<Fn>(function), std::move(
status()));
674 template <
typename Fn,
675 typename Ret = internal_result::InvokeResultType<Fn, Status&&>,
676 std::enable_if_t<std::is_void_v<Ret>,
int> = 0>
677 constexpr Result<T>
or_else(Fn&& function) && {
681 std::invoke(std::forward<Fn>(function),
status());
682 return std::move(*
this);
695 template <
typename Fn,
696 typename Ret = internal_result::InvokeResultType<Fn, T&>,
697 std::enable_if_t<std::is_copy_constructible_v<Ret>,
int> = 0>
702 return std::invoke(std::forward<Fn>(function),
value());
705 template <
typename Fn,
706 typename Ret = internal_result::InvokeResultType<Fn, T&&>,
707 std::enable_if_t<std::is_move_constructible_v<Ret>,
int> = 0>
710 return std::move(
status());
712 return std::invoke(std::forward<Fn>(function), std::move(
value()));
715 template <
typename Fn,
716 typename Ret = internal_result::InvokeResultType<Fn, T&>,
717 std::enable_if_t<std::is_copy_constructible_v<Ret>,
int> = 0>
718 constexpr Result<Ret>
transform(Fn&& function)
const& {
722 return std::invoke(std::forward<Fn>(function),
value());
725 template <
typename Fn,
726 typename Ret = internal_result::InvokeResultType<Fn, T&&>,
727 std::enable_if_t<std::is_move_constructible_v<Ret>,
int> = 0>
728 constexpr Result<Ret>
transform(Fn&& function)
const&& {
730 return std::move(
status());
732 return std::invoke(std::forward<Fn>(function), std::move(
value()));
737 template <
typename U>
738 constexpr void Assign(
const Result<U>& other);
739 template <
typename U>
740 constexpr void Assign(Result<U>&& other);
750 if (lhs.
ok() && rhs.
ok()) {
759 return !(lhs == rhs);
775 this->Assign(*other);
777 this->AssignStatus(other.
status());
783constexpr inline void Result<T>::Assign(Result<U>&& other) {
785 this->
Assign(*std::move(other));
787 this->AssignStatus(std::move(other).status());
791template <
typename... Args>
793 : Base(std::in_place, std::forward<Args>(args)...) {}
796template <
typename U,
typename... Args>
798 std::initializer_list<U> ilist,
800 : Base(std::in_place, ilist, std::forward<Args>(args)...) {}
804 return this->status_;
809 PW_ASSERT(this->status_.ok());
815 PW_ASSERT(this->status_.ok());
821 PW_ASSERT(this->status_.ok());
822 return std::move(this->data_);
827 PW_ASSERT(this->status_.ok());
828 return std::move(this->data_);
833 PW_ASSERT(this->status_.ok());
839 PW_ASSERT(this->status_.ok());
845 PW_ASSERT(this->status_.ok());
846 return std::move(this->data_);
851 PW_ASSERT(this->status_.ok());
852 return std::move(this->data_);
857 PW_ASSERT(this->status_.ok());
863 PW_ASSERT(this->status_.ok());
873 return std::forward<U>(default_value);
880 return std::move(this->data_);
882 return std::forward<U>(default_value);
898constexpr T&& ConvertToValue(Result<T>& result) {
899 return std::move(result).value();
constexpr const T & operator*() const &PW_ATTRIBUTE_LIFETIME_BOUND
Definition: result.h:832
constexpr Result(const Result &)=default
Result<T> is copy constructible if T is copy constructible.
constexpr Result(const Result< U > &other)
Definition: result.h:196
T & emplace(Args &&... args)
Definition: result.h:535
constexpr Result & operator=(Result &&)=default
constexpr Result(U &&u)
Definition: result.h:412
constexpr Result< T > or_else(Fn &&function) const &
Definition: result.h:647
constexpr void IgnoreError() const
Definition: result.h:886
constexpr Result & operator=(U &&v)
Definition: result.h:374
constexpr bool ok() const
Definition: result.h:447
constexpr const T & value() const &PW_ATTRIBUTE_LIFETIME_BOUND
Definition: result.h:808
constexpr const T * operator->() const PW_ATTRIBUTE_LIFETIME_BOUND
Definition: result.h:856
constexpr Result & operator=(const Result< U > &other)
Definition: result.h:266
constexpr T value_or(U &&default_value) const &
constexpr Result & operator=(const Result &)=default
constexpr Ret and_then(Fn &&function) &
Definition: result.h:585
constexpr Status status() const
Definition: result.h:803
T value_type
Definition: result.h:153
constexpr Result< Ret > transform(Fn &&function) &
Definition: result.h:698
constexpr Result(U &&v)
Definition: result.h:311
constexpr Result(Result &&)=default
Result<T> is move constructible if T is move constructible.
#define PW_ATTRIBUTE_LIFETIME_BOUND
Definition: compiler.h:273
Result(T value) -> Result< T >
Deduction guide to allow Result(v) rather than Result<T>(v).
constexpr Status OkStatus()
Definition: status.h:450
Status Assign(InlineString<> &string, std::string_view view)
Definition: util.h:142
The Pigweed namespace.
Definition: alignment.h:27