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