The ultimate design goal is to generalize and enhance the discriminated union construct, without compromising its functionality. That is, there should be little or no room for choosing:

struct U {
  union { T0 m0; ...; TN mN; };
  std::size_t which;
} u;


using V = eggs::variant<T0, ..., TN>;
V v;

In particular:

  • The size of V shall match that of the corresponding U. Any active member of v shall be allocated in a region of V suitably aligned for the types T0, ... TN; the use of additional storage, such as dynamic memory, is not permitted.

  • Well defined semantics of u shall be matched or improved by v. Undefined behavior, such as referring to a non-active member of u, shall not be allowed by the interface of v.

  • All special member functions shall be provided by V with the expected semantics.

The interface is largely based on that of std::optional<T>. The conceptual model for optional<T> is that of a discriminated union of types nullopt_t and T. The design decisions taken for optional<T> easily translate to variant<Ts...>, whose conceptual model is that of a discriminated union of the empty type and the types in Ts. The semantics of all special member functions and relational operators, as well as the interface for switching the active member —via construction, assignment, or emplacement—, derives from optional<T>.

Access to the active member is based on the design of std::function, which gives back a pointer to the target if queried with the correct target type —as a poor man's dynamic_cast—. Additionally, it is also possible to obtain a void pointer to the active member (if any), which proved useful to simplify the implementation of helper functions.

Finally, helper classes similar to those of std::tuple are provided, as well as index or type based element access —albeit with surprising semantics, closer to those of a runtime-checked cast—.

Copyright Agustín Bergé, Fusion Fenix 2014-2017

Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE.txt or copy at