std::monostate was released with std::variant in C++17.
Essentially, std::monostate is a type where all its instances have exactly the same (and empty) state, hence its name.
Think of its implementation as being similar to something like this:
class empty { };
And what is it useful for?
- An instance of this class can be used to represent the initial value of a
std::variantwhen declared as its first type. Astd::variantMUST always contain a valid value, sostd::monostateis quite useful when its initial value is not known a priori or when the other data types do not have default constructors.
std::variant<std::monostate, int, std::string> value; // here value is instantiated using std::monostate.
- It can be used when representing a “no-value” as a valid
std::variantvalue is needed.
std::variant<int, std::string, std::monostate> value{2}; // stores an int.
value = std::monostate{}; // now stores a new instance of std::monostate.
- Independently from
std::variant, it can be used when a class with no data is required. A concrete example?
Currently, I am working on a UI layout system. The layout_container can store UI widgets and, depending on the layout policies used, they need to specify a “constraint.” The constraint could be a relative XY coordinate, or a position inside a border_layout (north, south, etc.) or NOTHING (for example, in a flow-based layout, the UI controls are positioned one next to the other, flowing like text, and thus, they do not need any constraint).
So I could define my layout_container like this:
template <typename Constraint, typename LayoutPolicy>
class layout_container;
and have the specific types like:
using border_layout_container = layout_container<border_layout_constraint, border_layout_policy>;
using xy_layout_container = layout_container<xy_layout_constraint, xy_layout_policy>;
using flow_layout_container = layout_container<std::monostate, flow_layout_policy>;
I do not need to change anything in my layout_container to support (or not) constraints thanks to std::monostate.
- Additionally,
std::monostateimplements all comparison operators (operator==,operator!=, etc.). All instances are equal, by the way. Finally,std::monostatecan also be used as a key onstd::unordered_mapinstances because it provides a specialization forstd::hash.
Want to read more about std::variant? Check this out!