This article introduces the new
std::any class in C++ 17. It can store all values that are “Copy Constructible”. In the following we will first introduce the basic usage of
std::any, and then describe the practical use of it.
The use of the
std::any class is broken down as follows.
- Constructed objects
- Assigning operators
- any_cast function
- has_value member function
- reset member function
- emplace member function
- type member function
std::any category is defined in the
<any> header file. There are several ways of constructing
- construct a
std::anyobject without a value using the Default Constructor.
- pass the value to the
std::anyconstructor so that it stores the value.
- construct a
std::anyobject “with the value of
ValueType” with the
std::make_any<ValueType>function. The arguments to
std::make_anyare passed to the constructors of
Regardless of how the
std::any object is constructed, the value stored must be
Copy Constructible. For example, if we try to pass a non-copyable
std::unique_ptr object into the
std::any construct, we get the following compilation error.
We can replace the values stored in
std::any by assigning operators. The type of value can also be changed at will.
We can also assign one
std::any object to another
The values stored by
std::any must be read in the
std::any_cast style function. Because we must pass in the stencil argument of
std::any_cast, we must know the type of the value stored in
std::any. If the type of the template parameter is different from the type of the
std::any stored value,
std::any_cast will throw the following exception to
std::any_cast object passed to
std::any_cast is a reference type,
std::any_cast will return a copy of the stored value.
If we want direct access to the values in the
std::any object, the argument type of
std::any_cast must be
std::any * (pointer type). Example.
has_value member function
has_value member function returns whether
std::any has the value.
reset member function
reset member function clears the values stored in
emplace member function
emplace<ValueType>(...) The member function constructs a value of type
ValueType within the
std::any object. The argument of
emplace becomes the argument of the
ValueType construct. If the
std::any object already has a value, the existing value will be deconstructed first.
operator=(ValueType(...)) is similar to
operator=(ValueType(...), but if the Copy Constructor (or Move Constructor) of
ValueType has to take longer to execute,
emplace<ValueType>(...) can save us the execution time of copying (or moving) objects from a
ValueType temporary object.
type member function
type member function returns Run-Time Type Information (RTTI) for a numeric type. The
type member function and the
typeid keyword are used to select the appropriate
std::any_cast function template parameter for the run-time. If the
std::any object has no value, the
type member function will return
Context of use
When designing APIs, we often have to keep their Context Object for the Callback function. The Context Object is then passed to the Callback function when it is called. However, we run into two problems at this point:
- The party holding the Context Object does not want to impose too many restrictions on the Context Object, nor does it want to know the type of the Context Object.
- The party holding the Context Object must know how to deconstruct the Context Object.
std::any solves these two problems elegantly. A simple example is the following.
callback2 will belong to separate C++ source files. The
EventSource does not need to know the actual type of the Context Object. Each Callback will obtain its own Context Object via
std::any_cast according to its own logic after getting the
- cppreference.com, std::any