text: /*
   * Copyright 2004-present Facebook, Inc.
   *
   * 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.
   */
  
  #pragma once
  
  #include <initializer_list>
  #include <new>
  #include <type_traits>
  #include <utility>
  
  #include <folly/Launder.h>
  #include <folly/Portability.h>
  #include <folly/Traits.h>
  #include <folly/Utility.h>
  
  /**
   * An instance of `Replaceable<T>` wraps an instance of `T`.
   *
   * You access the inner `T` instance with `operator*` and `operator->` (as if
   * it were a smart pointer).
   *
   * `Replaceable<T>` adds no indirection cost and performs no allocations.
   *
   * `Replaceable<T>` has the same size and alignment as `T`.
   *
   * You can replace the `T` within a `Replaceable<T>` using the `emplace` method
   * (presuming that it is constructible and destructible without throwing
   * exceptions). If the destructor or constructor you're using could throw an
   * exception you should use `Optional<T>` instead, as it's not a logic error
   * for that to be empty.
   *
   * Frequently Asked Questions
   * ==========================
   *
   * Why does this need to be so complicated?
   * ----------------------------------------
   *
   * If a `T` instance contains `const`-qualified member variables or reference
   * member variables we can't safely replace a `T` instance by destructing it
   * manually and using placement new. This is because compilers are permitted to
   * assume that the `const` or reference members of a named, referenced, or
   * pointed-to object do not change.
   *
   * For pointed-to objects in allocated storage you can use the pointer returned
   * by placement new or use the `launder` function to get a pointer to the new
   * object.  Note that `launder` doesn't affect its argument, it's still
   * undefined behaviour to use the original pointer. And none of this helps if
   * the object is a local or a member variable because the destructor call will
   * not have been laundered. In summary, this is the only way to use placement
   * new that is both simple and safe:
   *
   *      T* pT = new T(...);
   *      pT->~T();
   *      pT = ::new (pT) T(...);
   *      delete pT;
   *
   * What are the other safe solutions to this problem?
   * --------------------------------------------------
   *
   * * Ask the designer of `T` to de-`const` and -`reference` the members of `T`.
   *  - Makes `T` harder to reason about
   *  - Can reduce the performance of `T` methods
   *  - They can refuse to make the change
   * * Put the `T` on the heap and use a raw/unique/shared pointer.
   *  - Adds a level of indirection, costing performance.
   *  - Harder to reason about your code as you need to check for nullptr.
   * * Put the `T` in an `Optional`.
   *  - Harder to reason about your code as you need to check for None.
   * * Pass the problem on, making the new code also not-replaceable
   *  - Contagion is not really a solution
   *
   * Are there downsides to this?
   * ----------------------------
   *
   * There is a potential performance penalty after converting `T` to
   * `Replaceable<T>` if you have non-`T`-member-function code which repeatedly
   * examines the value of a `const` or `reference` data member of `T`, because
   * the compiler now has to look at the value each time whereas previously it
   * was permitted to load it once up-front and presume that it could never
   * change.
   *
   * Usage notes
   * ===========
   *
   * Don't store a reference to the `T` within a `Replaceable<T>` unless you can
   * show that its lifetime does not cross an `emplace` call. For safety a
   * reasonable rule is to always use `operator*()` to get a fresh temporary each
   * time you need a `T&.
   *
   * If you store a pointer to the `T` within a `Replaceable<T>` you **must**
   * launder it after each call to `emplace` before using it. Again you can
   * reasonably choose to always use `operator->()` to get a fresh temporary each
   * time you need a `T*.
   *
   * Thus far I haven't thought of a good reason to use `Replaceable<T>` or
   * `Replaceable<T> const&` as a function parameter type.
   *
   * `Replaceable<T>&` can make sense to pass to a function that conditionally
   * replaces the `T`, where `T` has `const` or reference member variables.
   *
   * The main use of `Replaceable<T>` is as a class member type or a local type
   * in long-running functions.
   *
   * It's probably time to rethink your design choices if you end up with
   * `Replaceable<Replaceable<T>>`, `Optional<Replaceable<T>>`,
   * `Replaceable<Optional<T>>`, `unique_ptr<Replaceable<T>>` etc. except as a
   *  result of template expansion.
   */
  
  namespace folly {
  template <class T>
  class Replaceable;
  
  namespace replaceable_detail {
  /* Mixin templates to give `replaceable<T>` the following properties:
   *
   * 1. Trivial destructor if `T` has a trivial destructor; user-provided
   *    otherwise
   * 2. Move constructor if `T` has a move constructor; deleted otherwise
   * 3. Move assignment operator if `T` has a move constructor; deleted
   *    otherwise
   * 4. Copy constructor if `T` has a copy constructor; deleted otherwise
   * 5. Copy assignment operator if `T` has a copy constructor; deleted
   *    otherwise
   *
   * Has to be done in this way because we can't `enable_if` them away
   */
  template <
      class T,
      bool /* true iff destructible */,
      bool /* true iff trivially destructible */>
  struct dtor_mixin;
  
  /* Destructible and trivially destructible */
  template <class T>
  struct dtor_mixin<T, true, true> {};
  
  /* Destructible and not trivially destructible */
  template <class T>
  struct dtor_mixin<T, true, false> {
    dtor_mixin() = default;
    dtor_mixin(dtor_mixin&&) = default;
    dtor_mixin(dtor_mixin const&) = default;
    dtor_mixin& operator=(dtor_mixin&&) = default;
    dtor_mixin& operator=(dtor_mixin const&) = default;
    ~dtor_mixin() noexcept(std::is_nothrow_destructible<T>::value) {
      T* destruct_ptr = launder(reinterpret_cast<T*>(
          reinterpret_cast<Replaceable<T>*>(this)->storage_));
      destruct_ptr->~T();
    }
  };
  
  /* Not destructible */
  template <class T, bool A>
  struct dtor_mixin<T, false, A> {
    dtor_mixin() = default;
    dtor_mixin(dtor_mixin&&) = default;
    dtor_mixin(dtor_mixin const&) = default;
    dtor_mixin& operator=(dtor_mixin&&) = default;
    dtor_mixin& operator=(dtor_mixin const&) = default;
    ~dtor_mixin() = delete;
  };
  
  template <
      class T,
      bool /* true iff default constructible */,
      bool /* true iff move constructible */>
  struct default_and_move_ctor_mixin;
  
  /* Not default-constructible and not move-constructible */
  template <class T>
  struct default_and_move_ctor_mixin<T, false, false> {
    default_and_move_ctor_mixin() = delete;
    default_and_move_ctor_mixin(default_and_move_ctor_mixin&&) = delete;
    default_and_move_ctor_mixin(default_and_move_ctor_mixin const&) = default;
    default_and_move_ctor_mixin& operator=(default_and_move_ctor_mixin&&) =
        default;
    default_and_move_ctor_mixin& operator=(default_and_move_ctor_mixin const&) =
        default;
  
   protected:
    inline explicit default_and_move_ctor_mixin(int) {}
  };
  
  /* Default-constructible and move-constructible */
  template <class T>
  struct default_and_move_ctor_mixin<T, true, true> {
    inline default_and_move_ctor_mixin() noexcept(
        std::is_nothrow_constructible<T>::value) {
      ::new (reinterpret_cast<Replaceable<T>*>(this)->storage_) T();
    }
    inline default_and_move_ctor_mixin(
        default_and_move_ctor_mixin&&
            other) noexcept(std::is_nothrow_constructible<T, T&&>::value) {
      ::new (reinterpret_cast<Replaceable<T>*>(this)->storage_)
          T(*std::move(reinterpret_cast<Replaceable<T>&>(other)));
    }
    default_and_move_ctor_mixin(default_and_move_ctor_mixin const&) = default;
    default_and_move_ctor_mixin& operator=(default_and_move_ctor_mixin&&) =
        default;
    inline default_and_move_ctor_mixin& operator=(
        default_and_move_ctor_mixin const&) = default;
  
   protected:
    inline explicit default_and_move_ctor_mixin(int) {}
  };
  
  /* Default-constructible and not move-constructible */
  template <class T>
  struct default_and_move_ctor_mixin<T, true, false> {
    inline default_and_move_ctor_mixin() noexcept(
        std::is_nothrow_constructible<T>::value) {
      ::new (reinterpret_cast<Replaceable<T>*>(this)->storage_) T();
    }
    default_and_move_ctor_mixin(default_and_move_ctor_mixin&&) = delete;
    default_and_move_ctor_mixin(default_and_move_ctor_mixin const&) = default;
    default_and_move_ctor_mixin& operator=(default_and_move_ctor_mixin&&) =
        default;
    default_and_move_ctor_mixin& operator=(default_and_move_ctor_mixin const&) =
        default;
  
   protected:
    inline explicit default_and_move_ctor_mixin(int) {}
  };
  
  /* Not default-constructible but is move-constructible */
  template <class T>
  struct default_and_move_ctor_mixin<T, false, true> {
    default_and_move_ctor_mixin() = delete;
    inline default_and_move_ctor_mixin(
        default_and_move_ctor_mixin&&
            other) noexcept(std::is_nothrow_constructible<T, T&&>::value) {
      ::new (reinterpret_cast<Replaceable<T>*>(this)->storage_)
          T(*std::move(reinterpret_cast<Replaceable<T>&>(other)));
    }
    default_and_move_ctor_mixin(default_and_move_ctor_mixin const&) = default;
    default_and_move_ctor_mixin& operator=(default_and_move_ctor_mixin&&) =
        default;
    default_and_move_ctor_mixin& operator=(default_and_move_ctor_mixin const&) =
        default;
  
   protected:
    inline explicit default_and_move_ctor_mixin(int) {}
  };
  
  template <class T, bool /* true iff destructible and move constructible */>
  struct move_assignment_mixin;
  
  /* Not (destructible and move-constructible) */
  template <class T>
  struct move_assignment_mixin<T, false> {
    move_assignment_mixin() = default;
    move_assignment_mixin(move_assignment_mixin&&) = default;
    move_assignment_mixin(move_assignment_mixin const&) = default;
    move_assignment_mixin& operator=(move_assignment_mixin&&) = delete;
    move_assignment_mixin& operator=(move_assignment_mixin const&) = default;
  };
  
  /* Both destructible and move-constructible */
  template <class T>
  struct move_assignment_mixin<T, true> {
    move_assignment_mixin() = default;
    move_assignment_mixin(move_assignment_mixin&&) = default;
    move_assignment_mixin(move_assignment_mixin const&) = default;
    inline move_assignment_mixin&
    operator=(move_assignment_mixin&& other) noexcept(
        std::is_nothrow_destructible<T>::value&&
            std::is_nothrow_move_constructible<T>::value) {
      T* destruct_ptr = launder(reinterpret_cast<T*>(
          reinterpret_cast<Replaceable<T>*>(this)->storage_));
      destruct_ptr->~T();
      ::new (reinterpret_cast<Replaceable<T>*>(this)->storage_)
          T(*std::move(reinterpret_cast<Replaceable<T>&>(other)));
      return *this;
    }
    move_assignment_mixin& operator=(move_assignment_mixin const&) = default;
  };
  
  template <class T, bool /* true iff copy constructible */>
  struct copy_ctor_mixin;
  
  /* Not copy-constructible */
  template <class T>
  struct copy_ctor_mixin<T, false> {
    copy_ctor_mixin() = default;
    copy_ctor_mixin(copy_ctor_mixin&&) = default;
    copy_ctor_mixin(copy_ctor_mixin const&) = delete;
    copy_ctor_mixin& operator=(copy_ctor_mixin&&) = default;
    copy_ctor_mixin& operator=(copy_ctor_mixin const&) = delete;
  };
  
  /* Copy-constructible */
  template <class T>
  struct copy_ctor_mixin<T, true> {
    copy_ctor_mixin() = default;
    inline copy_ctor_mixin(copy_ctor_mixin const& other) noexcept(
        std::is_nothrow_constructible<T, T const&>::value) {
      ::new (reinterpret_cast<Replaceable<T>*>(this)->storage_)
          T(*reinterpret_cast<Replaceable<T> const&>(other));
    }
    copy_ctor_mixin(copy_ctor_mixin&&) = default;
    copy_ctor_mixin& operator=(copy_ctor_mixin&&) = default;
    copy_ctor_mixin& operator=(copy_ctor_mixin const&) = default;
  };
  
  template <class T, bool /* true iff destructible and copy constructible */>
  struct copy_assignment_mixin;
  
  /* Not (destructible and copy-constructible) */
  template <class T>
  struct copy_assignment_mixin<T, false> {
    copy_assignment_mixin() = default;
    copy_assignment_mixin(copy_assignment_mixin&&) = default;
    copy_assignment_mixin(copy_assignment_mixin const&) = default;
    copy_assignment_mixin& operator=(copy_assignment_mixin&&) = default;
    copy_assignment_mixin& operator=(copy_assignment_mixin const&) = delete;
  };
  
  /* Both destructible and copy-constructible */
  template <class T>
  struct copy_assignment_mixin<T, true> {
    copy_assignment_mixin() = default;
    copy_assignment_mixin(copy_assignment_mixin&&) = default;
    copy_assignment_mixin(copy_assignment_mixin const&) = default;
    copy_assignment_mixin& operator=(copy_assignment_mixin&&) = default;
    inline copy_assignment_mixin&
    operator=(copy_assignment_mixin const& other) noexcept(
        std::is_nothrow_destructible<T>::value&&
            std::is_nothrow_copy_constructible<T>::value) {
      T* destruct_ptr = launder(reinterpret_cast<T*>(
          reinterpret_cast<Replaceable<T>*>(this)->storage_));
      destruct_ptr->~T();
      ::new (reinterpret_cast<Replaceable<T>*>(this)->storage_)
          T(*reinterpret_cast<Replaceable<T> const&>(other));
      return *this;
    }
  };
  
  template <typename T>
  struct is_constructible_from_replaceable
      : std::integral_constant<
            bool,
            std::is_constructible<T, Replaceable<T>&>::value ||
                std::is_constructible<T, Replaceable<T>&&>::value ||
                std::is_constructible<T, const Replaceable<T>&>::value ||
                std::is_constructible<T, const Replaceable<T>&&>::value> {};
  
  template <typename T>
  struct is_convertible_from_replaceable
      : std::integral_constant<
            bool,
            std::is_convertible<Replaceable<T>&, T>::value ||
                std::is_convertible<Replaceable<T>&&, T>::value ||
                std::is_convertible<const Replaceable<T>&, T>::value ||
                std::is_convertible<const Replaceable<T>&&, T>::value> {};
  } // namespace replaceable_detail
  
  // Type trait template to statically test whether a type is a specialization of
  // Replaceable
  template <class T>
  struct is_replaceable : std::false_type {};
  
  template <class T>
  struct is_replaceable<Replaceable<T>> : std::true_type {};
  
  // Function to make a Replaceable with a type deduced from its input
  template <class T>
  constexpr Replaceable<std::decay_t<T>> make_replaceable(T&& t) {
    return Replaceable<std::decay_t<T>>(std::forward<T>(t));
  }
  
  template <class T, class... Args>
  constexpr Replaceable<T> make_replaceable(Args&&... args) {
    return Replaceable<T>(in_place, std::forward<Args>(args)...);
  }
  
  template <class T, class U, class... Args>
  constexpr Replaceable<T> make_replaceable(
      std::initializer_list<U> il,
      Args&&... args) {
    return Replaceable<T>(in_place, il, std::forward<Args>(args)...);
  }
  
  template <class T>
  class alignas(T) Replaceable
      : public replaceable_detail::dtor_mixin<
            T,
            std::is_destructible<T>::value,
            std::is_trivially_destructible<T>::value>,
        public replaceable_detail::default_and_move_ctor_mixin<
            T,
            std::is_default_constructible<T>::value,
            std::is_move_constructible<T>::value>,
        public replaceable_detail::
            copy_ctor_mixin<T, std::is_copy_constructible<T>::value>,
        public replaceable_detail::move_assignment_mixin<
            T,
            std::is_destructible<T>::value &&
                std::is_move_constructible<T>::value>,
        public replaceable_detail::copy_assignment_mixin<
            T,
            std::is_destructible<T>::value &&
                std::is_copy_constructible<T>::value> {
    using ctor_base = replaceable_detail::default_and_move_ctor_mixin<
        T,
        std::is_constructible<T>::value,
        std::is_move_constructible<T>::value>;
  
   public:
    using value_type = T;
  
    /* Rule-of-zero default- copy- and move- constructors. The ugly code to make
     * these work are above, in namespace folly::replaceable_detail.
     */
    constexpr Replaceable() = default;
    constexpr Replaceable(const Replaceable&) = default;
    constexpr Replaceable(Replaceable&&) = default;
  
    /* Rule-of-zero copy- and move- assignment operators. The ugly code to make
     * these work are above, in namespace folly::replaceable_detail.
     *
     * Note - these destruct the `T` and then in-place construct a new one based
     * on what is in the other replaceable; they do not invoke the assignment
     * operator of `T`.
     */
    Replaceable& operator=(const Replaceable&) = default;
    Replaceable& operator=(Replaceable&&) = default;
  
    /* Rule-of-zero destructor. The ugly code to make this work is above, in
     * namespace folly::replaceable_detail.
     */
    ~Replaceable() = default;
  
    /**
     * Constructors; these are modeled very closely on the definition of
     * `std::optional` in C++17.
     */
    template <
        class... Args,
        std::enable_if_t<std::is_constructible<T, Args&&...>::value, int> = 0>
    FOLLY_CPP14_CONSTEXPR explicit Replaceable(in_place_t, Args&&... args)
        // clang-format off
        noexcept(std::is_nothrow_constructible<T, Args&&...>::value)
        // clang-format on
        : ctor_base(0) {
      ::new (storage_) T(std::forward<Args>(args)...);
    }
  
    template <
        class U,
        class... Args,
        std::enable_if_t<
            std::is_constructible<T, std::initializer_list<U>, Args&&...>::value,
            int> = 0>
    FOLLY_CPP14_CONSTEXPR explicit Replaceable(
        in_place_t,
        std::initializer_list<U> il,
        Args&&... args)
        // clang-format off
        noexcept(std::is_nothrow_constructible<
            T,
            std::initializer_list<U>,
            Args&&...>::value)
        // clang-format on
        : ctor_base(0) {
      ::new (storage_) T(il, std::forward<Args>(args)...);
    }
  
    template <
        class U = T,
        std::enable_if_t<
            std::is_constructible<T, U&&>::value &&
                !std::is_same<std::decay_t<U>, in_place_t>::value &&
                !std::is_same<Replaceable<T>, std::decay_t<U>>::value &&
                std::is_convertible<U&&, T>::value,
            int> = 0>
    FOLLY_CPP14_CONSTEXPR /* implicit */ Replaceable(U&& other)
        // clang-format off
        noexcept(std::is_nothrow_constructible<T, U&&>::value)
        // clang-format on
        : ctor_base(0) {
      ::new (storage_) T(std::forward<U>(other));
    }
  
    template <
        class U = T,
        std::enable_if_t<
            std::is_constructible<T, U&&>::value &&
                !std::is_same<std::decay_t<U>, in_place_t>::value &&
                !std::is_same<Replaceable<T>, std::decay_t<U>>::value &&
                !std::is_convertible<U&&, T>::value,
            int> = 0>
    FOLLY_CPP14_CONSTEXPR explicit Replaceable(U&& other)
        // clang-format off
        noexcept(std::is_nothrow_constructible<T, U&&>::value)
        // clang-format on
        : ctor_base(0) {
      ::new (storage_) T(std::forward<U>(other));
    }
  
    template <
        class U,
        std::enable_if_t<
            std::is_constructible<T, const U&>::value &&
                !replaceable_detail::is_constructible_from_replaceable<
                    T>::value &&
                !replaceable_detail::is_convertible_from_replaceable<T>::value &&
                std::is_convertible<const U&, T>::value,
            int> = 0>
    /* implicit */ Replaceable(const Replaceable<U>& other)
        // clang-format off
        noexcept(std::is_nothrow_constructible<T, U const&>::value)
        // clang-format on
        : ctor_base(0) {
      ::new (storage_) T(*other);
    }
  
    template <
        class U,
        std::enable_if_t<
            std::is_constructible<T, const U&>::value &&
                !replaceable_detail::is_constructible_from_replaceable<
                    T>::value &&
                !replaceable_detail::is_convertible_from_replaceable<T>::value &&
                !std::is_convertible<const U&, T>::value,
            int> = 0>
    explicit Replaceable(const Replaceable<U>& other)
        // clang-format off
        noexcept(std::is_nothrow_constructible<T, U const&>::value)
        // clang-format on
        : ctor_base(0) {
      ::new (storage_) T(*other);
    }
  
    template <
        class U,
        std::enable_if_t<
            std::is_constructible<T, U&&>::value &&
                !replaceable_detail::is_constructible_from_replaceable<
                    T>::value &&
                !replaceable_detail::is_convertible_from_replaceable<T>::value &&
                std::is_convertible<U&&, T>::value,
            int> = 0>
    /* implicit */ Replaceable(Replaceable<U>&& other)
        // clang-format off
        noexcept(std::is_nothrow_constructible<T, U&&>::value)
        // clang-format on
        : ctor_base(0) {
      ::new (storage_) T(std::move(*other));
    }
  
    template <
        class U,
        std::enable_if_t<
            std::is_constructible<T, U&&>::value &&
                !replaceable_detail::is_constructible_from_replaceable<
                    T>::value &&
                !replaceable_detail::is_convertible_from_replaceable<T>::value &&
                !std::is_convertible<U&&, T>::value,
            int> = 0>
    explicit Replaceable(Replaceable<U>&& other)
        // clang-format off
        noexcept(std::is_nothrow_constructible<T, U&&>::value)
        // clang-format on
        : ctor_base(0) {
      ::new (storage_) T(std::move(*other));
    }
  
    /**
     * `emplace` destructs the contained object and in-place constructs the
     * replacement.
     *
     * The destructor must not throw (as usual). The constructor must not throw
     * because that would violate the invariant that a `Replaceable<T>` always
     * contains a T instance.
     *
     * As these methods are `noexcept` the program will be terminated if an
     * exception is thrown. If you are encountering this issue you should look at
     * using `Optional` instead.
     */
    template <class... Args>
    T& emplace(Args&&... args) noexcept {
      T* destruct_ptr = launder(reinterpret_cast<T*>(storage_));
      destruct_ptr->~T();
      return *::new (storage_) T(std::forward<Args>(args)...);
    }
  
    template <class U, class... Args>
    T& emplace(std::initializer_list<U> il, Args&&... args) noexcept {
      T* destruct_ptr = launder(reinterpret_cast<T*>(storage_));
      destruct_ptr->~T();
      return *::new (storage_) T(il, std::forward<Args>(args)...);
    }
  
    /**
     * `swap` just calls `swap(T&, T&)`.
     *
     * Should be `noexcept(std::is_nothrow_swappable<T>::value)` but we don't
     * depend on C++17 features.
     */
    void swap(Replaceable& other) {
      using std::swap;
      swap(*(*this), *other);
    }
  
    /**
     * Methods to access the contained object. Intended to be very unsurprising.
     */
    constexpr const T* operator->() const {
      return launder(reinterpret_cast<T const*>(storage_));
    }
  
    FOLLY_CPP14_CONSTEXPR T* operator->() {
      return launder(reinterpret_cast<T*>(storage_));
    }
  
    constexpr const T& operator*() const & {
      return *launder(reinterpret_cast<T const*>(storage_));
    }
  
    FOLLY_CPP14_CONSTEXPR T& operator*() & {
      return *launder(reinterpret_cast<T*>(storage_));
    }
  
    FOLLY_CPP14_CONSTEXPR T&& operator*() && {
      return std::move(*launder(reinterpret_cast<T*>(storage_)));
    }
  
    constexpr const T&& operator*() const && {
      return std::move(*launder(reinterpret_cast<T const*>(storage_)));
    }
  
   private:
    friend struct replaceable_detail::dtor_mixin<
        T,
        std::is_destructible<T>::value,
        std::is_trivially_destructible<T>::value>;
    friend struct replaceable_detail::default_and_move_ctor_mixin<
        T,
        std::is_default_constructible<T>::value,
        std::is_move_constructible<T>::value>;
    friend struct replaceable_detail::
        copy_ctor_mixin<T, std::is_constructible<T, T const&>::value>;
    friend struct replaceable_detail::move_assignment_mixin<
        T,
        std::is_destructible<T>::value && std::is_move_constructible<T>::value>;
    friend struct replaceable_detail::copy_assignment_mixin<
        T,
        std::is_destructible<T>::value && std::is_copy_constructible<T>::value>;
    std::aligned_storage_t<sizeof(T), alignof(T)> storage_[1];
  };
  
  #if __cplusplus > 201402L
  // C++17 allows us to define a deduction guide:
  template <class T>
  Replaceable(T)->Replaceable<T>;
  #endif
  } // namespace folly
  