Concepts
<emphasis>BoundedType</emphasis> The requirements on a bounded type are as follows: CopyConstructible or MoveConstructible. Destructor upholds the no-throw exception-safety guarantee. Complete at the point of variant template instantiation. (See boost::recursive_wrapper<T> for a type wrapper that accepts incomplete types to enable recursive variant types.) Every type specified as a template argument to variant must at minimum fulfill the above requirements. In addition, certain features of variant are available only if its bounded types meet the requirements of these following additional concepts: Assignable: variant is itself Assignable if and only if every one of its bounded types meets the requirements of the concept. (Note that top-level const-qualified types and reference types do not meet these requirements.) MoveAssignable: variant is itself MoveAssignable if and only if every one of its bounded types meets the requirements of the concept. (Note that top-level const-qualified types and reference types do not meet these requirements.) DefaultConstructible [20.1.4]: variant is itself DefaultConstructible if and only if its first bounded type (i.e., T1) meets the requirements of the concept. EqualityComparable: variant is itself EqualityComparable if and only if every one of its bounded types meets the requirements of the concept. LessThanComparable: variant is itself LessThanComparable if and only if every one of its bounded types meets the requirements of the concept. OutputStreamable: variant is itself OutputStreamable if and only if every one of its bounded types meets the requirements of the concept. Hashable: variant is itself Hashable if and only if every one of its bounded types meets the requirements of the concept.
<emphasis>StaticVisitor</emphasis> The requirements on a static visitor of a type T are as follows: Must allow invocation as a function by overloading operator(), unambiguously accepting any value of type T. Must expose inner type result_type. C++14 compatible compilers could detect result_type automatically, but will stick to result_type if it is defined. (See boost::visitor_ptr for a solution to using functions as visitors.) If result_type is not void, then each operation of the function object must return a value implicitly convertible to result_type.
Examples The following class satisfies the requirements of a static visitor of several types (i.e., explicitly: int and std::string; or, e.g., implicitly: short and const char *; etc.): class my_visitor : public boost::static_visitor<int> { public: int operator()(int i) { return i * 2; } int operator()(const std::string& s) { return s.length(); } }; Another example is the following class, whose function-call operator is a member template, allowing it to operate on values of many types. Thus, the following class is a visitor of any type that supports streaming output (e.g., int, double, std::string, etc.): class printer : public boost::static_visitor<> { template <typename T> void operator()(const T& t) { std::cout << t << std::endl; } }; C++14 compatible compilers detect result_type automatically: boost::variant<int, float> v; // ... boost::apply_visitor( [](auto val) { return std::to_string(val); }, v );
<emphasis>OutputStreamable</emphasis> The requirements on an output streamable type T are as follows: For any object t of type T, std::cout << t must be a valid expression.
<emphasis>Hashable</emphasis> The requirements on an hashable type T are as follows: For any object t of type T, boost::hash<T>()(t) must be a valid expression.