Trial.Dynamic Overview Trial.Dynamic is a C++11 header-only library with a C++ dynamic variable. The dynamic variable is a tagged union whose type and value can change dynamically during program execution. The dynamic variable supports fundamental data types[1][2] and strings. The dynamic variable supports sequenced and associative containers of dynamic variables and can therefore act as a heterogenous tree data structure. The dynamic variable meets the requirements of Container and therefore works with standard C++ algorithms. The dynamic variable can be customized with an allocator. The resemblance between dynamic::variable and std::variant is obvious, but there are notable differences. While std::variant supports custom types, dynamic::variable is restricted to the above-mentioned data types and containers. This restriction enables dynamic::variable to adhere to the Container concept, and thus to have a richer interface that works with algorithms. Dynamic variables are useful for carrying configuration data, constructing parse trees for data formats, and protocol serialization. Tutorial All examples throughout this documentation assumes the following prologue: #include <trial/dynamic/variable.hpp> namespace dynamic = trial::dynamic; Shapeshifter A default-initialized dynamic::variable has no value. No value is represented with the dynamic::nullable type. We can query if the variable has a certain type with the dynamic::variable::is<T>() member function. We can also examine if the variable has no value by comparing it with dynamic::null. // Create an empty variable dynamic::variable data; assert(data.is<dynamic::nullable>()); assert(data == dynamic::null); If we assign a boolean value to the above variable then the variable changes into a boolean type. // Change into boolean data = true; assert(data.is<bool>()); assert(data == true); We can even change it into an array by assigning an initializer list to it. // Change into array data = { 1, 20, 300 }; assert(data.is<dynamic::array>()); assert(data.size() == 3); assert(data[0] == 1); assert(data[1] == 20); assert(data[2] == 300); Finally, we will change our variable into an associative array. // Change into associative array data = { { "alpha", null }, // nullable { "bravo", true }, // boolean { "charlie", 2 }, // integer { "delta", 3.0 }, // floating-point number { "echo", "blue" }, // string { "foxtrot", { 1, 2, 3 } }, // nested array of integers { "golf", { { "level", 2 } } } // nested associative array }; assert(data.is<dynamic::map>()); assert(data.size() == 7); Algorithms Accumulation Suppose we have a dynamic variable that contains an array of integers. dynamic::variable data = { 1, 20, 300 }; We can calculate the sum of this array with the std::accumulate() algorithm. As std::accumulate() works on homogeneous types, the initial value must be a dynamic::variable. We could wrap zero with dynamic::variable(0), but in the example below we simply start with a empty dynamic variable. The empty dynamic variable behaves as a zero value when used in integer additions, so the resulting dynamic variable will contain an integer type. #include <numeric> // Calculate sum auto sum = std::accumulate(data.begin(), data.end(), dynamic::variable()); assert(sum.is<int>()); assert(sum == 1 + 20 + 300); 1. Sign-less characters (char, wchar_t, char16_t, and char32_t) are not supported directly, but only indirectly via strings. 2. void is not a regular type, so it has been replaced with the dynamic::nullable type and the dynamic::null value.