• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2020 The Pigweed Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 // use this file except in compliance with the License. You may obtain a copy of
5 // the License at
6 //
7 //     https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 // License for the specific language governing permissions and limitations under
13 // the License.
14 #pragma once
15 
16 #include <algorithm>
17 
18 #include "pw_assert/light.h"
19 #include "pw_status/status.h"
20 
21 namespace pw {
22 
23 // A Result represents the result of an operation which can fail. It is a
24 // convenient wrapper around returning a Status alongside some data when the
25 // status is OK.
26 template <typename T>
27 class Result {
28  public:
Result(T && value)29   constexpr Result(T&& value) : value_(std::move(value)), status_(OkStatus()) {}
Result(const T & value)30   constexpr Result(const T& value) : value_(value), status_(OkStatus()) {}
31 
32   template <typename... Args>
Result(std::in_place_t,Args &&...args)33   constexpr Result(std::in_place_t, Args&&... args)
34       : value_(std::forward<Args>(args)...), status_(OkStatus()) {}
35 
Result(Status status)36   constexpr Result(Status status) : dummy_({}), status_(status) {
37     PW_ASSERT(!status_.ok());
38   }
Result(Status::Code code)39   constexpr Result(Status::Code code) : dummy_({}), status_(code) {
40     PW_ASSERT(!status_.ok());
41   }
42 
43   constexpr Result(const Result&) = default;
44   constexpr Result& operator=(const Result&) = default;
45 
46   constexpr Result(Result&&) = default;
47   constexpr Result& operator=(Result&&) = default;
48 
status()49   constexpr Status status() const { return status_; }
ok()50   constexpr bool ok() const { return status_.ok(); }
51 
value()52   constexpr T& value() & {
53     PW_ASSERT(status_.ok());
54     return value_;
55   }
56 
value()57   constexpr const T& value() const& {
58     PW_ASSERT(status_.ok());
59     return value_;
60   }
61 
value()62   constexpr T&& value() && {
63     PW_ASSERT(status_.ok());
64     return std::move(value_);
65   }
66 
67   template <typename U>
value_or(U && default_value)68   constexpr T value_or(U&& default_value) const& {
69     if (ok()) {
70       PW_MODIFY_DIAGNOSTICS_PUSH();
71       // GCC 10 emits -Wmaybe-uninitialized warnings about value_.
72       PW_MODIFY_DIAGNOSTIC_GCC(ignored, "-Wmaybe-uninitialized");
73       return value_;
74       PW_MODIFY_DIAGNOSTICS_POP();
75     }
76     return std::forward<U>(default_value);
77   }
78 
79   template <typename U>
value_or(U && default_value)80   constexpr T value_or(U&& default_value) && {
81     if (ok()) {
82       return std::move(value_);
83     }
84     return std::forward<U>(default_value);
85   }
86 
87  private:
88   struct Dummy {};
89 
90   union {
91     T value_;
92 
93     // Ensure that there is always a trivial constructor for the union.
94     Dummy dummy_;
95   };
96   Status status_;
97 };
98 
99 }  // namespace pw
100