Lumiera  0.pre.03
»edit your freedom«
variant.hpp File Reference

Go to the source code of this file.

Description

A typesafe union record to carry embedded values of unrelated type.

This file defines a simple alternative to boost::variant. It pulls in fewer headers, has a shorter code path and is hopefully more readable, but also doesn't deal with alignment issues and is not threadsafe.

Deliberately, the design rules out re-binding of the contained type. Thus, once created, a variant must hold a valid element and always an element of the same type. Beyond that, variant elements are copyable and mutable. Direct access requires knowledge of the embedded type (no switch-on type). Type mismatch is checked at runtime. As a fallback, we provide a visitor scheme for generic access.

The design restrictions were chosen deliberately, since a variant type might promote "probe and switch on type" style programming, which is known to be fragile. Likewise, we do not want to support mutations of the variant type at runtime. Basically, using a variant record is recommended only if either the receiving context has structural knowledge about the type to expect, or when a visitor implementation can supply a sensible handling for all the possible types. As an alternative, you might consider the lib::PolymorphicValue to hold types implementing a common interface.

implementation notes

We use a "double capsule" implementation technique similar to lib::OpaqueHolder. In fact, Variant is almost identical to the latter, just omitting unnecessary flexibility. The outer capsule exposes the public handling interface, while the inner, private capsule is a polymorphic value holder. Since C++ as such does not support polymorphic values, the inner capsule is placed "piggyback" into a char buffer. The actual value is carried within yet another, nested char buffer. Thus, effectively the first "slot" of the storage will hold the VTable pointer, thereby encoding the actual type information – leading to a storage requirement of MAX<TYPES...> plus one "slot" for the VTable. (with "slot" we denote the smallest disposable storage size for the given platform after alignment, typically the size of a size_t).

To support copying and assignment of variant instances, but limit these operations to variants holding the same type, we use a virtual assignment function. In case the concrete type does not support assignment or copy construction, the respective access function is replaced by an implementation raising a runtime error.

Note
we use a Visitor interface generated through metaprogramming. This may generate a lot of warnings "-Woverloaded-virtual", since one handle(TX) function may shadow other handle(..) functions from the inherited (generated) Visitor interface. These warnings are besides the point, since not the client uses these functions, but the Variant does, after upcasting to the interface. Make sure you define your specialisations with the override modifier; when done so, it is safe to disable this warning here.
See also
Veriant_test
lib::diff::GenNode
virtual-copy-support.hpp

Definition in file variant.hpp.

#include "lib/error.hpp"
#include "lib/meta/typelist.hpp"
#include "lib/meta/typelist-util.hpp"
#include "lib/meta/generator.hpp"
#include "lib/meta/virtual-copy-support.hpp"
#include "lib/format-obj.hpp"
#include "lib/util.hpp"
#include <type_traits>
#include <utility>
#include <string>

Classes

struct  Variant< TYPES >::Buff< TY >
 concrete inner capsule specialised for a given type More...
 
struct  Variant< TYPES >::Buffer
 Inner capsule managing the contained object (interface) More...
 
struct  CanBuildFrom< X, TYPES >
 
struct  CanBuildFrom< const char [len], Node< string, TYPES > >
 < esp. allow to build string from char literal More...
 
struct  CanBuildFrom< const X, Node< X, TYPES > >
 
struct  CanBuildFrom< X, Node< T, TYPES > >
 
struct  CanBuildFrom< X, Node< X, TYPES > >
 
struct  CanBuildFrom< X, NullType >
 
struct  FirstMatchingType< TYPES, _P_ >
 Helper to pick the first type from a type sequence, which fulfils the predicate (meta function) given as template. More...
 
struct  FirstMatchingType< Node< T, TYPES >, _P_ >
 
struct  FirstMatchingType< Types< TYPES... >, _P_ >
 
struct  Identity< T >
 
class  Variant< TYPES >::Predicate
 
struct  VFunc< RET >::ValueAcceptInterface< VAL >
 how to treat one single type in visitation More...
 
class  Variant< TYPES >
 Typesafe union record. More...
 
struct  VFunc< RET >
 
class  Variant< TYPES >::Visitor
 to be implemented by the client for visitation More...
 

Namespaces

 lib
 Implementation namespace for support and library code.