# Concepts

## BoundedType

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.

## StaticVisitor

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
        );

## OutputStreamable

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.

## Hashable

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.