<commit_before>/******************************************************************************
 *                       ____    _    _____                                   *
 *                      / ___|  / \  |  ___|    C++                           *
 *                     | |     / _ \ | |_       Actor                         *
 *                     | |___ / ___ \|  _|      Framework                     *
 *                      \____/_/   \_|_|                                      *
 *                                                                            *
 * Copyright (C) 2011 - 2017                                                  *
 * <NAME> <<EMAIL>ik.charousset (at) haw-hamburg.de>                *
 *                                                                            *
 * Distributed under the terms and conditions of the BSD 3-Clause License or  *
 * (at your option) under the terms and conditions of the Boost Software      *
 * License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE.       *
 *                                                                            *
 * If you did not receive a copy of the license files, see                    *
 * http://opensource.org/licenses/BSD-3-Clause and                            *
 * http://www.boost.org/LICENSE_1_0.txt.                                      *
 ******************************************************************************/

#ifndef CAF_EXPECTED_HPP
#define CAF_EXPECTED_HPP

#include "caf/config.hpp"

#include <new>
#include <memory>
#include <ostream>
#include <type_traits>

#include "caf/unit.hpp"
#include "caf/error.hpp"
#include "caf/unifyn.hpp"

namespace caf {

/// Helper class to construct an `expected<T>` that represents no error.
/// @relates expected
struct no_error_t {};

/// The only instance of ::no_error_t.
/// @relates expected
constexpr no_error_t no_error = no_error_t{};

/// Represents the result of a computation which can either complete
/// successfully with an instance of type `T` or fail with an `error`.
/// @tparam T The type of the result.
template <typename T>
class expected {
public:
  // -- member types -----------------------------------------------------------

  using value_type = T;

  // -- static member variables ------------------------------------------------

  /// Stores whether move construct and move assign never throw.
  static constexpr bool nothrow_move
    = std::is_nothrow_move_constructible<T>::value
      && std::is_nothrow_move_assignable<T>::value;

  /// Stores whether copy construct and copy assign never throw.
  static constexpr bool nothrow_copy
    = std::is_nothrow_copy_constructible<T>::value
      && std::is_nothrow_copy_assignable<T>::value;

  // -- constructors, destructors, and assignment operators --------------------

  template <class U>
  expected(U x,
           typename std::enable_if<std::is_convertible<U, T>::value>::type* = nullptr)
      : engaged_(true) {
    new (&value_) T(std::move(x));
  }

  expected(T&& x) noexcept(nothrow_move) : engaged_(true) {
    new (&value_) T(std::move(x));
  }

  expected(const T& x) noexcept(nothrow_copy) : engaged_(true) {
    new (&value_) T(x);
  }

  expected(caf::error e) noexcept : engaged_(false) {
    new (&error_) caf::error{std::move(e)};
  }

  expected(no_error_t) noexcept : engaged_(false) {
    new (&error_) caf::error{};
  }

  expected(const expected& other) noexcept(nothrow_copy) {
    construct(other);
  }

  template <class Code, class E = enable_if_has_make_error_t<Code>>
  expected(Code code) : engaged_(false) {
    new (&error_) caf::error(make_error(code));
  }

  expected(expected&& other) noexcept(nothrow_move) {
    construct(std::move(other));
  }

  ~expected() {
    destroy();
  }

  expected& operator=(const expected& other) noexcept(nothrow_copy) {
    if (engaged_ && other.engaged_)
      value_ = other.value_;
    else if (!engaged_ && !other.engaged_)
      error_ = other.error_;
    else {
      destroy();
      construct(other);
    }
    return *this;
  }

  expected& operator=(expected&& other) noexcept(nothrow_move) {
    if (engaged_ && other.engaged_)
      value_ = std::move(other.value_);
    else if (!engaged_ && !other.engaged_)
      error_ = std::move(other.error_);
    else {
      destroy();
      construct(std::move(other));
    }
    return *this;
  }

  expected& operator=(const T& x) noexcept(nothrow_copy) {
    if (engaged_) {
      value_ = x;
    } else {
      destroy();
      engaged_ = true;
      new (&value_) T(x);
    }
    return *this;
  }


  expected& operator=(T&& x) noexcept(nothrow_move) {
    if (engaged_) {
      value_ = std::move(x);
    } else {
      destroy();
      engaged_ = true;
      new (&value_) T(std::move(x));
    }
    return *this;
  }

  template <class U>
  typename std::enable_if<std::is_convertible<U, T>::value, expected&>::type
  operator=(U x) {
    return *this = T{std::move(x)};
  }

  expected& operator=(caf::error e) noexcept {
    if (!engaged_)
      error_ = std::move(e);
    else {
      destroy();
      engaged_ = false;
      new (&value_) caf::error(std::move(e));
    }
    return *this;
  }

  template <class Code>
  enable_if_has_make_error_t<Code, expected&> operator=(Code code) {
    return *this = make_error(code);
  }

  // -- modifiers --------------------------------------------------------------

  /// @copydoc cvalue
  T& value() noexcept {
    CAF_ASSERT(engaged_);
    return value_;
  }

  /// @copydoc cvalue
  T& operator*() noexcept {<commit_msg>Fix bug in disengaged expected<T><commit_after>/******************************************************************************
 *                       ____    _    _____                                   *
 *                      / ___|  / \  |  ___|    C++                           *
 *                     | |     / _ \ | |_       Actor                         *
 *                     | |___ / ___ \|  _|      Framework                     *
 *                      \____/_/   \_|_|                                      *
 *                                                                            *
 * Copyright (C) 2011 - 2017                                                  *
 * <NAME> <<EMAIL>inik.charousset (at) haw-hamburg.de>                *
 *                                                                            *
 * Distributed under the terms and conditions of the BSD 3-Clause License or  *
 * (at your option) under the terms and conditions of the Boost Software      *
 * License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE.       *
 *                                                                            *
 * If you did not receive a copy of the license files, see                    *
 * http://opensource.org/licenses/BSD-3-Clause and                            *
 * http://www.boost.org/LICENSE_1_0.txt.                                      *
 ******************************************************************************/

#ifndef CAF_EXPECTED_HPP
#define CAF_EXPECTED_HPP

#include "caf/config.hpp"

#include <new>
#include <memory>
#include <ostream>
#include <type_traits>

#include "caf/unit.hpp"
#include "caf/error.hpp"
#include "caf/unifyn.hpp"

namespace caf {

/// Helper class to construct an `expected<T>` that represents no error.
/// @relates expected
struct no_error_t {};

/// The only instance of ::no_error_t.
/// @relates expected
constexpr no_error_t no_error = no_error_t{};

/// Represents the result of a computation which can either complete
/// successfully with an instance of type `T` or fail with an `error`.
/// @tparam T The type of the result.
template <typename T>
class expected {
public:
  // -- member types -----------------------------------------------------------

  using value_type = T;

  // -- static member variables ------------------------------------------------

  /// Stores whether move construct and move assign never throw.
  static constexpr bool nothrow_move
    = std::is_nothrow_move_constructible<T>::value
      && std::is_nothrow_move_assignable<T>::value;

  /// Stores whether copy construct and copy assign never throw.
  static constexpr bool nothrow_copy
    = std::is_nothrow_copy_constructible<T>::value
      && std::is_nothrow_copy_assignable<T>::value;

  // -- constructors, destructors, and assignment operators --------------------

  template <class U>
  expected(U x,
           typename std::enable_if<std::is_convertible<U, T>::value>::type* = nullptr)
      : engaged_(true) {
    new (&value_) T(std::move(x));
  }

  expected(T&& x) noexcept(nothrow_move) : engaged_(true) {
    new (&value_) T(std::move(x));
  }

  expected(const T& x) noexcept(nothrow_copy) : engaged_(true) {
    new (&value_) T(x);
  }

  expected(caf::error e) noexcept : engaged_(false) {
    new (&error_) caf::error{std::move(e)};
  }

  expected(no_error_t) noexcept : engaged_(false) {
    new (&error_) caf::error{};
  }

  expected(const expected& other) noexcept(nothrow_copy) {
    construct(other);
  }

  template <class Code, class E = enable_if_has_make_error_t<Code>>
  expected(Code code) : engaged_(false) {
    new (&error_) caf::error(make_error(code));
  }

  expected(expected&& other) noexcept(nothrow_move) {
    construct(std::move(other));
  }

  ~expected() {
    destroy();
  }

  expected& operator=(const expected& other) noexcept(nothrow_copy) {
    if (engaged_ && other.engaged_)
      value_ = other.value_;
    else if (!engaged_ && !other.engaged_)
      error_ = other.error_;
    else {
      destroy();
      construct(other);
    }
    return *this;
  }

  expected& operator=(expected&& other) noexcept(nothrow_move) {
    if (engaged_ && other.engaged_)
      value_ = std::move(other.value_);
    else if (!engaged_ && !other.engaged_)
      error_ = std::move(other.error_);
    else {
      destroy();
      construct(std::move(other));
    }
    return *this;
  }

  expected& operator=(const T& x) noexcept(nothrow_copy) {
    if (engaged_) {
      value_ = x;
    } else {
      destroy();
      engaged_ = true;
      new (&value_) T(x);
    }
    return *this;
  }


  expected& operator=(T&& x) noexcept(nothrow_move) {
    if (engaged_) {
      value_ = std::move(x);
    } else {
      destroy();
      engaged_ = true;
      new (&value_) T(std::move(x));
    }
    return *this;
  }

  template <class U>
  typename std::enable_if<std::is_convertible<U, T>::value, expected&>::type
  operator=(U x) {
    return *this = T{std::move(x)};
  }

  expected& operator=(caf::error e) noexcept {
    if (!engaged_)
      error_ = std::move(e);
    else {
      destroy();
      engaged_ = false;
      new (&error_) caf::error(std::move(e));
    }
    return *this;
  }

  template <class Code>
  enable_if_has_make_error_t<Code, expected&> operator=(Code code) {
    return *this = make_error(code);
  }

  // -- modifiers --------------------------------------------------------------

  /// @copydoc cvalue
  T& value() noexcept {
    CAF_ASSERT(engaged_);
    return value_;
  }

  /// @copydoc cvalue
  T& operator*() noexcept {
{'fraction_non_alphanumeric': 0.18235610543302852, 'fraction_numerical': 0.002510310202617895, 'mean_word_length': 1.868346618668038, 'pattern_counts': {'":': 0, '<': 50, '<?xml version=': 0, '>': 50, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 30, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1334570', 'n_tokens_mistral': 3316, 'n_tokens_neox': 3180, 'n_words': 758}