Repository: bitcoin/bitcoin
File: src/util/result.h (C/C++)

Code before:
// Copyright (c) 2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or https://www.opensource.org/licenses/mit-license.php.

#ifndef BITCOIN_UTIL_RESULT_H
#define BITCOIN_UTIL_RESULT_H

#include <attributes.h>
#include <util/translation.h>

#include <variant>

namespace util {

struct Error {
    bilingual_str message;
};

//! The util::Result class provides a standard way for functions to return
//! either error messages or result values.
//!
//! It is intended for high-level functions that need to report error strings to
//! end users. Lower-level functions that don't need this error-reporting and
//! only need error-handling should avoid util::Result and instead use standard
//! classes like std::optional, std::variant, and std::tuple, or custom structs
//! and enum types to return function results.
//!
//! Usage examples can be found in \example ../test/result_tests.cpp, but in
//! general code returning `util::Result<T>` values is very similar to code
//! returning `std::optional<T>` values. Existing functions returning
//! `std::optional<T>` can be updated to return `util::Result<T>` and return
//! error strings usually just replacing `return std::nullopt;` with `return
//! util::Error{error_string};`.
template <class M>
class Result
{
private:
    using T = std::conditional_t<std::is_same_v<M, void>, std::monostate, M>;

    std::variant<bilingual_str, T> m_variant;

    //! Disallow copy constructor, require Result to be moved for efficiency.
    Result(const Result&) = delete;

    //! Disallow operator= to avoid confusion in the future when the Result
    //! class gains support for richer error reporting, and callers should have
    //! ability to set a new result value without clearing existing error
    //! messages.
    Result& operator=(const Result&) = delete;
    Result& operator=(Result&&) = delete;

Review comment (suggestion):
In commit "Add util::Expected (std::expected)" (fa1eee4f46fd089d6e19b124addee7c7679585f4)

IMO std::optional and std::variant are still appropriate to use in many cases and it would nice to keep mentioning them.

Code after:
// Copyright (c) 2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or https://www.opensource.org/licenses/mit-license.php.

#ifndef BITCOIN_UTIL_RESULT_H
#define BITCOIN_UTIL_RESULT_H

#include <attributes.h>
#include <util/translation.h>

#include <variant>

namespace util {

struct Error {
    bilingual_str message;
};

//! The util::Result class provides a standard way for functions to return
//! either error messages or result values.
//!
//! It is intended for high-level functions that need to report error strings to
//! end users. Lower-level functions that don't need this error-reporting and
//! that only need error-handling should avoid util::Result and instead use
//! util::Expected, std::optional, std::variant, or custom structs
//! and enum types to return function results.
//!
//! Usage examples can be found in \example ../test/result_tests.cpp, but in
//! general code returning `util::Result<T>` values is very similar to code
//! returning `std::optional<T>` values. Existing functions returning
//! `std::optional<T>` can be updated to return `util::Result<T>` and return
//! error strings usually just replacing `return std::nullopt;` with `return
//! util::Error{error_string};`.
template <class M>
class Result
{
private:
    using T = std::conditional_t<std::is_same_v<M, void>, std::monostate, M>;

    std::variant<bilingual_str, T> m_variant;

    //! Disallow copy constructor, require Result to be moved for efficiency.
    Result(const Result&) = delete;

    //! Disallow operator= to avoid confusion in the future when the Result
    //! class gains support for richer error reporting, and callers should have
    //! ability to set a new result value without clearing existing error
    //! messages.
    Result& operator=(const Result&) = delete;
    Result& operator=(Result&&) = delete;