https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120088

Jonathan Wakely <redi at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
   Last reconfirmed|                            |2025-05-06
     Ever confirmed|0                           |1
           Keywords|                            |rejects-valid
             Status|UNCONFIRMED                 |NEW

--- Comment #1 from Jonathan Wakely <redi at gcc dot gnu.org> ---
The libstdc++ implementation can be reduced to the following, which is rejected
the same way:

#include <memory>

struct unexpected { };

template<typename T, typename E>
struct expected
{
  constexpr expected(unexpected) noexcept : m_unex(), m_has_value(false) { }
  constexpr expected() noexcept : m_void(), m_has_value(true) { }
  expected(const expected&) = default;
  constexpr ~expected() = default;

  expected& operator=(const expected&) = delete;

  constexpr expected&
  operator=(const expected& x)
  requires true
  {
    if (x.m_has_value)
      emplace();
    else
      m_assign_unex(x.m_unex);
    return *this;
  }

  constexpr void emplace()
  {
    if (!m_has_value)
    {
      std::destroy_at(&m_unex);
      m_has_value = true;
    }
  }

    constexpr void
    m_assign_unex(const E& v)
    {
      if (m_has_value)
        {
          std::construct_at(&m_unex, v);
          m_has_value = false;
        }
      else
        m_unex = v;
    }

  union {
    struct { } m_void;
    E m_unex;
  };

  bool m_has_value;
};

constexpr bool quux() {
  expected<void, int> foo1{unexpected{}};
  expected<void, int> foo2{};
  foo1 = foo2;
  [[maybe_unused]] expected<void, int> foo3{foo1};
  return true;
}

static_assert(quux());


I'm not sure what needs to be changed here.

Reply via email to