Skip to content

iceoryx_utils/cxx/expected.hpp🔗

Namespaces🔗

Name
iox
building block to easily create free function for logging in a library context
iox::cxx
iox::cxx::internal

Classes🔗

Name
struct iox::cxx::internal::HasInvalidStateMember
Type trait which verifies whether the passed type T has INVALID_STATE std::true_type overload chosen when INVALID_STATE is present, otherwise std::false_type.
struct iox::cxx::internal::IsOptional
Type trait which verifies whether the passed type T is of type cxx::optional.
struct iox::cxx::ErrorTypeAdapter
Generic adapter to access INVALID_STATE member or value.
struct iox::cxx::success
helper struct to create an expected which is signalling success more easily
struct iox::cxx::success< void >
helper struct to create an error only expected which is signalling success more easily
struct iox::cxx::error
helper struct to create an expected which is signalling an error more easily
class iox::cxx::expected< ErrorType >
expected implementation from the C++20 proposal with C++11. The interface is inspired by the proposal but it has changes since we are not allowed to throw an exception.
class iox::cxx::expected< ValueType, ErrorType >
specialization of the expected class which can contain an error as well as a success value
class iox::cxx::expected< void, ErrorType >

Source code🔗

// Copyright (c) 2019 - 2020 by Robert Bosch GmbH. All rights reserved.
// Copyright (c) 2020 - 2021 by Apex.AI Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// SPDX-License-Identifier: Apache-2.0
#ifndef IOX_UTILS_CXX_EXPECTED_HPP
#define IOX_UTILS_CXX_EXPECTED_HPP

#include "iceoryx_utils/cxx/attributes.hpp"
#include "iceoryx_utils/cxx/function_ref.hpp"
#include "iceoryx_utils/cxx/optional.hpp"
#include "iceoryx_utils/cxx/variant.hpp"

#include <utility>

namespace iox
{
namespace cxx
{
namespace internal
{
template <typename, typename = void>
struct HasInvalidStateMember;

template <typename...>
struct IsOptional;
} // namespace internal

template <typename T>
struct ErrorTypeAdapter
{
    static_assert(internal::HasInvalidStateMember<T>::value,
                  "T must have an INVALID_STATE value/member. Alternatively write an ErrorTypeAdapter specialisation "
                  "for your type");

    static T getInvalidState() noexcept;
};

template <typename T = void>
struct success
{
    success(const T& t) noexcept;

    success(T&& t) noexcept;
    template <typename... Targs>

    success(Targs&&... args) noexcept;

    T value;
};

template <>
struct success<void>
{
};

template <typename T>
struct error
{
    error(const T& t) noexcept;

    error(T&& t) noexcept;

    template <typename... Targs>
    error(Targs&&... args) noexcept;

    T value;
};

template <typename... T>
class IOX_NO_DISCARD expected;

template <typename ErrorType>
class IOX_NO_DISCARD expected<ErrorType>
{
  public:
    expected() = delete;

    expected(const expected&) noexcept = default;

    expected(expected&& rhs) noexcept;

#if defined(_WIN32)
    template <typename ValueType>
    expected(const expected<ValueType, ErrorType>& rhs) noexcept;

    template <typename ValueType>
    expected(expected<ValueType, ErrorType>&& rhs) noexcept;
#endif
    ~expected() = default;

    expected& operator=(const expected&);

    expected& operator=(expected&& rhs) noexcept;

#if defined(_WIN32)
    template <typename ValueType>
    expected& operator=(const expected<ValueType, ErrorType>& rhs) noexcept;

    template <typename ValueType>
    expected& operator=(expected<ValueType, ErrorType>&& rhs) noexcept;
#endif

    expected(const success<void>& successValue) noexcept;

    expected(const error<ErrorType>& errorValue) noexcept;

    expected(error<ErrorType>&& errorValue) noexcept;

    static expected create_value() noexcept;

    template <typename... Targs>
    static expected create_error(Targs&&... args) noexcept;

    explicit operator bool() const noexcept;

    bool has_error() const noexcept;

    ErrorType& get_error() & noexcept;

    const ErrorType& get_error() const& noexcept;

    ErrorType&& get_error() && noexcept;

    const expected& or_else(const cxx::function_ref<void(ErrorType&)>& callable) const noexcept;

    expected& or_else(const cxx::function_ref<void(ErrorType&)>& callable) noexcept;

    const expected& and_then(const cxx::function_ref<void()>& callable) const noexcept;

    expected& and_then(const cxx::function_ref<void()>& callable) noexcept;

  private:
    expected(variant<ErrorType>&& store, const bool hasError) noexcept;
    variant<ErrorType> m_store;
    bool m_hasError;
    static constexpr uint64_t ERROR_INDEX = 0U;
};

template <typename ValueType, typename ErrorType>
class IOX_NO_DISCARD expected<ValueType, ErrorType>
{
  public:
    expected() = delete;

    expected(const expected&) = default;

    expected(expected&& rhs) noexcept;

    ~expected() noexcept = default;

    expected& operator=(const expected&) noexcept;

    expected& operator=(expected&& rhs) noexcept;

    expected(const success<ValueType>& successValue) noexcept;

    expected(success<ValueType>&& successValue) noexcept;

    expected(const error<ErrorType>& errorValue) noexcept;

    expected(error<ErrorType>&& errorValue) noexcept;

    template <typename... Targs>
    static expected create_value(Targs&&... args) noexcept;

    template <typename... Targs>
    static expected create_error(Targs&&... args) noexcept;

    explicit operator bool() const noexcept;

    bool has_error() const noexcept;

    ErrorType& get_error() & noexcept;

    const ErrorType& get_error() const& noexcept;

    ErrorType&& get_error() && noexcept;

    ValueType& value() & noexcept;

    const ValueType& value() const& noexcept;

    ValueType&& value() && noexcept;

    ValueType value_or(const ValueType& value) const noexcept;

    ValueType value_or(const ValueType& value) noexcept;


    ValueType& operator*() noexcept;

    const ValueType& operator*() const noexcept;

    ValueType* operator->() noexcept;

    const ValueType* operator->() const noexcept;

    template <typename T>
    operator expected<T>() noexcept;

    template <typename T>
    operator expected<T>() const noexcept;

    const expected& or_else(const cxx::function_ref<void(ErrorType&)>& callable) const noexcept;

    expected& or_else(const cxx::function_ref<void(ErrorType&)>& callable) noexcept;

    const expected& and_then(const cxx::function_ref<void(ValueType&)>& callable) const noexcept;

    expected& and_then(const cxx::function_ref<void(ValueType&)>& callable) noexcept;

    template <typename Optional = ValueType,
              typename std::enable_if<internal::IsOptional<Optional>::value, int>::type = 0>
    const expected& and_then(const cxx::function_ref<void(typename Optional::type&)>& callable) const noexcept;

    template <typename Optional = ValueType,
              typename std::enable_if<internal::IsOptional<Optional>::value, int>::type = 0>
    expected& and_then(const cxx::function_ref<void(typename Optional::type&)>& callable) noexcept;

    template <typename Optional = ValueType,
              typename std::enable_if<internal::IsOptional<Optional>::value, int>::type = 0>
    [[deprecated]] const expected& if_empty(const cxx::function_ref<void()>& callable) const noexcept;

    template <typename Optional = ValueType,
              typename std::enable_if<internal::IsOptional<Optional>::value, int>::type = 0>
    [[deprecated]] expected& if_empty(const cxx::function_ref<void()>& callable) noexcept;

    optional<ValueType> to_optional() const noexcept;

  private:
    expected(variant<ValueType, ErrorType>&& f_store, const bool hasError) noexcept;
    variant<ValueType, ErrorType> m_store;
    bool m_hasError;
    static constexpr uint64_t VALUE_INDEX = 0U;
    static constexpr uint64_t ERROR_INDEX = 1U;
};

template <typename ErrorType>
class IOX_NO_DISCARD expected<void, ErrorType> : public expected<ErrorType>
{
  public:
    using expected<ErrorType>::expected;
};


} // namespace cxx
} // namespace iox

#include "iceoryx_utils/internal/cxx/expected.inl"

#endif // IOX_UTILS_CXX_EXPECTED_HPP

Updated on 31 May 2022 at 15:29:15 CEST