6

Here is described the nullopt_t and nullopt for the optional object proposed for c++:

struct nullopt_t{see below}; 
constexpr nullopt_t nullopt(unspecified);

[...] Type nullopt_t shall not have a default constructor. It shall be a literal type. Constant nullopt shall be initialized with an argument of literal type.

The reason for this is explained in the The op = {} syntax chapter of the document: for the op = {} to be unambiguous some tricks have to be adopted, one of which is that nullopt_t must not be default constructible.

My question is about what does the literal type means here? I found this SO post. So it looks to me that just another empty class would do. Could it also be a constructor taking a int?

What would be a minimal conforming nullopt_t class look like?

Something like this:

struct nullopt_t_construct_tag_t{};

struct nullopt_t {
  nullopt_t() = delete; // I know declaring it as deleted is redundant
  constexpr nullopt_t(nullopt_t_construct_tag_t) {};
};

constexpr nullopt_t nullopt(nullopt_t_construct_tag_t{});

Or this:

struct nullopt_t {
  nullopt_t() = delete;
  constexpr nullopt_t(int) {};
};

constexpr nullopt_t nullopt(0);
Community
  • 1
  • 1
bolov
  • 72,283
  • 15
  • 145
  • 224

1 Answers1

5

A minimal implementation is

struct nullopt_t {
    constexpr nullopt_t(int) {}
};

No default constructor will be implicitly declared, [class.ctor]/4:

If there is no user-declared constructor for class X, a constructor having no parameters is implicitly declared as defaulted (8.4).

... and nullopt_t can be constructed from int, a literal type.
Note that in your code a default constructor exists, though being defined as deleted.

The above definition does meet the requirements for a literal type:

A type is a literal type if it is:
(10.5) — a class type (Clause 9) that has all of the following properties:

  • it has a trivial destructor,
  • it is an aggregate type (8.5.1) or has at least one constexpr constructor [..] that is not a copy or move constructor, and
  • all of its non-static data members and base classes are of non-volatile literal types.
Columbo
  • 60,038
  • 8
  • 155
  • 203
  • Could this run into quality of implementation issues, where an `int` is passed to an optional, and it is converted to a `nullopt_t` and used to construct the optional, and unexpected things result? – Yakk - Adam Nevraumont Feb 17 '15 at 21:58
  • @Yakk If the value type of the optional can be constructed from an int, then overload resolution will make sure that the right constructor (template) is chosen. If not... Then you're correct. Making the above constructor explicit should solve that problem. – Columbo Feb 18 '15 at 09:03