There's a value stored in std::any
and I want to know if it's an integral value (char
, short
, int
, long
, both signed and unsigned) or a floating point value (float
, double
), or something else.
If I only had to check for int
values, I would do this:
std::any a;
if (a.type() == typeid(int)) {
// do some logic for int
}
But to do a giant if (a.type() == typeid(int) || a.type() == typeid(signed char)...)
for all the integral types in C++ seems... bad.
I could use is_arithmetic<T>
from type_traits
if I had the type T
accessible somehow but I don't, I only have std::any#type()
which returns std::type_info
.
Is there a way to accomplish this without many, many disjunctions in the if
condition?
(I'm using C++20 if it's important)
std::any
is a type erasure class.It only remembers the exact type, and the ability to cast back to that exact type (plus how to copy/move/destroy it).
If you want to remember other facts about a type stored, you have to do the work yourself.
There is no way to get at the
T
withinstd::any
without checking for that exactT
.In general, using
std::any
to shove "anything" into it with no control results in a mess.std::any
allows you to do this with an "open" set of types, so you can safely pass data from one spot of code to another while the intermediate code doesn't need to know what it is.It does not give you the ability to generate type-aware code using an unknown type.
To solve your problem, there are a number of solutions.
If your set of types you support is closed (fixed somehow), use
std::variant
.If the set of types is mostly closed, use
std::variant< bunch, of, types, std::any >
. Then you can deal with the "mostly closed" types as avariant
. Using code that blocks conversion tostd::any
if the type input can be converted-to any other type might be wise.If you are comfortable writing your own type erasure, you can write your own or augment
std::any
with extra information.You can write a utility function that does the massive if statement, possibly using templates, in time linear in the number of types.
For 1/2,
For 3, here is an example of an engine that makes type erasure this way a bit simpler; writing it yourself is possible. Then we simply:
For 4,
which is linear in
sizeof...(Ts)
.You could get fancy with hashes if
Ts...
is large, but I doubt it will get large enough. You still need to enumerate the types yourself;is_integral<T>
cannot be inverted by the C++ language.