As the C++ language is a strong typed language it is not possible to use the same variable to hold an integer, a real, or a string. In most of the cases, this is not a problem as this is a feature of the C++ language. However, some applications would require to store different kind of data in a same variable (like a database's fields). There are already existing solutions like union keyword in the C++ language, Boost::Variant, Boost::Any, or QVariant solution. However, some of them are only definable at compile time (union, Boost::Variant) or cannot freely convert stored value between different types (e.g. string to integer) like Boost::Any. In case the stored type is not known at run-time and the use of the run-time type information (RTTI) mechanism is discouraged, only the Qt class QVariant gives the possibity to store a generic content and convert it (if possible) in the desired type. However, the use of QVariant means you need to link your code the QtCore module which could be very heavy if you have a lightweight project. Moreover, QVariant could support more type than desired (QColor, QFont, QByteArray, etc.)

The class ma::Any was implemented to have a similiar behaviour than QVariant using the Boost naming convention. Indeed, the purpose of ma::Any is closer of Boost::Any than Boost::Variant.

The implementation of the class ma::Any relies heavily on the features introduced in the C++11 revision of the C++ standard (constexpr, variadic templates, initializer lists, static assertions, rvalue, move, etc.).

The internal behaviour of the class is mostly composed of three elements:

// Must be in a function. For example the main(). The scope of the registration
// is valid until the end of the program.
ma::Any::Register< Date, ma::converter<>, ma::converter<> >();
// ^^^^
// Registered type
// ^^^^^^^^^^^^^^^
// A Date stored in a ma::Any object
// can be converted to these types
// (none available in this example)
// ^^^^^^^^^^^^^^^
// A Date object can be created from another type
// (none available in this example)

When conversions are intended. the internal converter must be specialized in consequence. For example, if a Date can be converted to a std::string or created from a std::string, two specializations are required.

In case a user type has to be unregistered (e.g. plugin unloaded), the command ma::Any::Unregister must be called.

// The next line unregisters all the conversions related to a Date object.
// You can still store a Date object in ma::Any, but only a conversion to
// it its own type will be valid
ma::Any::Unregister();
ma::Any a(Date{2009,05,02});
ma::Date b = a; // 2009,05,02
std::string c = a; // empty string

Move assignement operator. In case the assigned object is not this one, the previous content is deleted and replaced by the content of the other object. The other object is then defined as null (method Any::isValid() returns true).