 Two weeks ago, I had a pleasure to give a talk at our local C++ User Group in Cracow. This time I spoke about vocabulary types from C++17: `std::optional`, `std::variant` and `std::any`.

## The Talk

During the presentation, I tried to explain the motivation and some most crucial use cases for the new types that we got in C++17.

For example for `std::variant` we can experiment with the code for computing roots of an equation:

``````// aX^2 + bX + c
? ? ? FindRoots(double a, double b, double c)
{
const auto delta = b * b - 4.0 * a * c;

if (delta > EPSILON)
{
const auto p = sqrt(delta);
const auto x1 = (-b + p) / (2.0 * a);
const auto x2 = (-b - p) / (2.0 * a);
return ? ?
}
else if (delta < -EPSILON)
return ? ? // no roots in real numbers...

return -b / (2.0 * a);
}
``````

What type should we return? How to transfer the information that we might have none, one or two roots of the equation?

Some options:

• use `int` as the return type and return number of roots, then take two double pointers or references to output the results.
• return `vector<double>` with the results
• return `tuple<int, double, double>` (integer for the number of results and then two possible values).

Or we can use `std::variant`:

``````// aX^2 + bX + c
using TRoots = std::variant<std::monostate,
double,
std::pair<double, double>>;

TRoots FindRoots(double a, double b, double c)
{
const auto delta = b*b-4.0*a*c;

if (delta > EPSILON)
{
auto p = sqrt(delta);
double x1 = (-b + p)/(2*a);
double x2 = (-b - p)/(2*a);
return std::pair(x1, x2);
}
else if (delta < -EPSILON)
return std::monostate();

return -b/(2*a);
}
``````

Now, with `std::variant` we can express all the possible options without any hacks or output parameters.

What do you think about such design?