vladon vladon - 1 month ago 11
C++ Question

optional std::nullopt_t implementation in libcxx

Clang implements

this way:

struct nullopt_t
explicit constexpr nullopt_t(int) noexcept {}

constexpr nullopt_t nullopt{0};

Why not simply:

struct nullopt_t{};

constexpr nullopt_t nullopt{};


hvd hvd

As mentioned on std::nullopt_t:


nullopt_t is not DefaultConstructible to support both op = {}; and op = nullopt; as the syntax for disengaging an optional object.

Now test this with your implementation:

struct nullopt_t { };
template <typename T>
struct optional {
  optional &operator=(nullopt_t);
  optional &operator=(const optional &);
  optional &operator=(optional &&);
  template <typename U>
  optional &operator=(U &&);
int main() {
  optional<int> oi;
  oi = {};

This fails, because the call to operator= is ambiguous. It could be an attempt to call operator=(nullopt_t), or it could be an attempt to call operator=(optional &&), and there is no language rule to resolve this ambiguity.

Therefore, unless there's a change to the language rules, or oi = {}; no longer needs to be valid, either nullopt_t or optional needs to not be default-constructible, and nullopt_t is the logical choice for that.