CppWAMP
C++11 client library for the WAMP protocol
Variants

A wamp::Variant is a discriminated union container that represents a JSON value. It behaves similarly to a dynamically-typed Javascript variable. Its underlying type can change at runtime, depending on the actual values assigned to them. Variants play a central role in CppWAMP, as they are used to represent dynamic data exchanged with a WAMP peer.

Variants can hold any of the following value types:

Array and Object variants are recursive composites: their element values are also variants which can themselves be arrays or objects.

Construction and Assignment

A default-constructed Variant starts out being null:

using namespace wamp;
Variant v; // v starts out being null

A Variant can also be constructed with an initial value:

using namespace wamp;
Variant v(42); // v starts out as an integer

The dynamic type of a Variant can change at runtime via assignment:

using namespace wamp;
Variant v; // v starts out being null
v = 42; // v becomes an integer
v = "hello"; // v becomes a string
v = null; // v becomes nullified
v = Array{123, false, "foo"}; // v becomes an array of variants

Checking Dynamic Type

Each Variant stores its current dynamic type as a wamp::TypeId enumerator. The dynamic type can be checked with wamp::Variant::typeId() or wamp::Variant::is<T>(). In addition, operator bool can be used to determine if a variant is null.

using namespace wamp;
Variant v; // v starts out being null
assert( !v ); // Check that the variant is indeed null
assert( v == null );
assert( v.typeId() == TypeId::null );
assert( v.is<Null>() );
assert( v.is<TypeId::null>() );
v = 42; // v becomes an integer
assert( !!v); // Check that the variant is no longer null
assert( v != null );
assert( v.typeId() == TypeId::integer );
assert( v.is<Int>() );
assert( v.is<TypeId::integer>() );

The isNumber non-member function can be used to check if a Variant is currently a number (Int, UInt, or Real). The isScalar non-member function checks if a variant is a boolean or a number:

using namespace wamp;
Variant v("hello"); // v starts out as a string
assert( !isNumber(v) );
assert( !isScalar(v) );
v = true; // v is now a boolean
assert ( !isNumber(v) );
assert ( isScalar(v) );
v = 123.4; // v is now a real number
assert ( isNumber(v) );
assert ( isScalar(v) );

Accessing Values

Variant values can be accessed directly using Variant::as<T>(). If the variant does not match the target type, a wamp::error::Access exception is thrown.

using namespace wamp;
Variant v(42); // v starts out as an Int
std::cout << v.as<Int>() << "\n"; // Prints 42
v.as<Int>() += 10;
std::cout << v.as<Int>() << "\n"; // Prints 52
try
{
std::cout << v.as<String>() << "\n"; // throws
}
catch (const error::Access& e)
{
std::cerr << e.what() << "\n";
}

Accessing Elements and Members

For convenience, elements can be accessed directly from array variants, using the [] operator taking an integer index:

using namespace wamp;
// v[0] = 42; // throws error::Access, because v does not
// contain an Array
v = Array{42, "foo", false}; // v now contains an Array
std::cout << v.size() << "\n"; // Prints 3
std::cout << v[1] << "\n"; // Prints "foo"
v[2] = "bar"; // Assigns string "bar" to third element
std::cout << v[2] << "\n"; // Prints "bar"
std::cout << v[3] << "\n"; // throws std::out_of_range

For convenience, members can be accessed directly from object variants, using the [] operator taking a string key:

using namespace wamp;
// v["key"] = 123; // throws error::Access, because v does not
// contain an Object
v = Object{{"key", "value"}}; // v now contains an Object
std::cout << v.size() << "\n"; // Prints 1
v["key"] = 123; // Assigns integer 123 to member "key"
std::cout << v["key"] << "\n"; // Prints 123

Binary Objects (BLOBs)

Variants may also contain arbitrary binary objects. Such binary objects must be stored in wamp::Blob, which is simply a wrapper around std::vector<uint8_t>.

using namespace wamp;
v = Blob{0x12, 0x34, 0x56}; // Assign a binary object of 3 bytes
for (auto byte: v.as<Blob>().data()) // Access byte data vector
std::cout << byte << " ";
std::cout << "\n";

When transmitted using JSON serialization, Blobs are encoded as Base64 strings prefixed with a nul character. For MsgPack, they are encoded in bin format.

Using Variants as Optional Values

Because variants can be null, they can be used to contain optional (i.e. nullable) values. The boolean conversion operator is useful for knowing if a variant is currently null:

using namespace wamp;
Variant v = 123;
if (!v) // Evaluates to false
std::cout << "The value is empty\n";
else
std::cout << "The value is " << v << "\n"; // Prints 123

The valueOr member function can be used to obtain a fallback value if a variant is null:

using namespace wamp;
Variant name; // name is currently null
std::cout << "Name is "
<< name.valueOr<std::string>("anonymous") // Prints "anonymous"
<< "\n";

Conversions

Sometimes, it's not possible to know what numeric type to expect from a WAMP peer. wamp::Variant::to lets you convert from any scalar type to a known destination type.

using namespace wamp;
Real x;
v = 42; // v is now an integer
x = v.to<Real>();
assert( x == 42 );
v = true; // v is now a boolean
v.to(x); // Alternate syntax, equivalent to x = v.to<Real>()
assert( x == 1 );
try
{
s = v.to<String>(); // Invalid conversion from boolean to string
}
catch (const error::Conversion& e)
{
std::cerr << e.what() << "\n";
}

Comparisons

Variant objects can be compared with each other, or with other values. For the comparison to be equal, both types must match. However, all numeric types are considered to be the same type for comparison purposes (this is to more closely match the behavior of the === operator in Javascript, where it does not distinguish between signed/unsigned or integer/floating-point numbers).

using namespace wamp;
Variant v; // Starts as null
Variant w; // Starts as null
assert( v == w ); // null == null is always true
v = 42; // v is now an integer
w = "42"; // w is now a string
assert( v != w ); // Types do not match
v = 123; // v is still an integer
w = 123.0; // w is now a real number
assert( v == w ); // Numeric types match for comparison purposes
v = 0; // v is still an integer
w = false; // w is now a boolean
assert( v != w ); // Types do not match
v = "hello"; // v is now a String
// String variants can be compared against `char` arrays:
assert( v == "hello" );

Output

wamp::Variant, wamp::Array, and wamp::Object objects can be outputted to a std::ostream:

using namespace wamp;
std::cout << v << "\n"; // Prints "null"
v = 42;
std::cout << v << "\n"; // Prints "42"
Array a{"foo", false, 123};
v = a;
std::cout << a << "\n"; // Prints "["foo", false, 123]"
std::cout << v << "\n"; // Prints "["foo", false, 123]"

Next: Connectors

wamp::Variant::typeId
TypeId typeId() const
Returns the id of the variant's current dynamic type.
Definition: variant.ipp:242
wamp::Blob
Contains binary data as an array of bytes.
Definition: blob.hpp:28
wamp::Null
Type used to represent a null or empty Variant value.
Definition: null.hpp:39
wamp::Variant
Discriminated union container that represents a JSON value.
Definition: variant.hpp:134
wamp::Variant::size
SizeType size() const
Returns the number of elements contained by the variant.
Definition: variant.ipp:254
wamp::Object
std::map< String, Variant > Object
Variant bound type for maps of variants.
Definition: variantdefs.hpp:52
wamp
Definition: anyhandler.hpp:36
wamp::Array
std::vector< Variant > Array
Variant bound type for arrays of variants.
Definition: variantdefs.hpp:51
wamp::Int
std::int64_t Int
Variant bound type for signed integers.
Definition: variantdefs.hpp:47
wamp::Blob::data
Data & data()
Obtains the blob's array of bytes.
Definition: blob.ipp:24
wamp::Real
double Real
Variant bound type for floating-point numbers.
Definition: variantdefs.hpp:49
wamp::Variant::is
bool is() const
Returns true iff the variant's current dynamic type matches the given TBound type parameter.
Definition: variant.hpp:798
wamp::Variant::valueOr
ValueTypeOf< T > valueOr(T &&fallback) const
Obtains the variant's value converted to the given type, or the given fallback value if the variant i...
Definition: variant.hpp:865
wamp::Variant::as
TBound & as()
Returns a reference to the variant's bound value.
Definition: variant.hpp:879
variant.hpp
Contains the declaration of Variant and other closely related types/functions.
wamp::error::Conversion
Exception type thrown when converting a Variant to an invalid type.
Definition: error.hpp:106
wamp::Variant::to
T to() const
Converts the variant's bound value to the given type.
Definition: variant.hpp:840
wamp::TypeId::null
@ null
For Variant::Null.
wamp::String
std::string String
Variant bound type for text strings.
Definition: variantdefs.hpp:50
wamp::isNumber
constexpr bool isNumber()
Determines if the given type is considered a number.
Definition: traits.hpp:77
wamp::error::Access
Exception type thrown when accessing a Variant as an invalid type.
Definition: error.hpp:97
wamp::TypeId::integer
@ integer
For Variant::Int.