C++:检查 std::any 中存储的值是否为整数
C++: check if the value stored in std::any is integral
std::any
中存储了一个值,我想知道它是否是整数值(char
、short
、int
、long
、有符号和无符号)或浮点值(float
、double
)或其他值。
如果我只需要检查 int
个值,我会这样做:
std::any a;
if (a.type() == typeid(int)) {
// do some logic for int
}
但是为 C++ 中的所有整数类型做一个巨大的 if (a.type() == typeid(int) || a.type() == typeid(signed char)...)
似乎......不好。
我可以使用 type_traits
中的 is_arithmetic<T>
如果我以某种方式可以访问 T
类型,但我没有,我只有 std::any#type()
而 returns std::type_info
.
有没有办法在 if
条件下没有很多很多析取的情况下完成这个?
(如果它很重要,我正在使用 C++20)
std::any
是类型擦除 class.
它只记住确切的类型,以及转换回那个确切类型的能力(以及如何 copy/move/destroy 它)。
如果您想记住有关存储类型的其他 个事实,您必须自己完成这项工作。
如果不检查确切的 T
,就无法到达 std::any
内的 T
。
一般来说,使用 std::any
将“任何东西”推入其中而无法控制会导致一团糟。 std::any
允许您使用一组“开放”类型来执行此操作,因此您可以安全地将数据从一个代码点传递到另一个代码点,而中间代码不需要知道它是什么。
它无法让您使用未知类型生成类型感知代码。
要解决您的问题,有多种解决方案。
如果您支持的类型集已关闭(以某种方式修复),请使用 std::variant
.
如果类型集大部分是封闭的,使用std::variant< bunch, of, types, std::any >
。然后您可以将“大部分封闭”类型作为 variant
处理。如果类型输入可以转换为任何其他类型,则使用阻止转换为 std::any
的代码可能是明智的。
如果您愿意编写自己的类型擦除,您可以编写自己的或使用额外信息扩充 std::any
。
您可以编写一个实用函数来执行大量 if 语句,可能使用模板,时间与类型数量呈线性关系。
对于 1/2,
auto is_integral_f = [](auto&& x){ return std::is_integral<std::decay_t<decltype(x)>>{}; };
std::variant<int,char,unsigned int, long, double, std::any> bob;
bob = 3;
assert( std::visit( is_integral_f, bob ) );
对于 3, 一个引擎,它使类型擦除变得更简单一些;自己写是可以的。那么我们就简单的:
auto is_integral = any_method<bool()>{ is_integral_f };
super_any<decltype(is_integral)> my_any;
my_any bob = 3;
my_any alice = 3.14;
assert( (bob->*is_integral)() );
assert( !(alice->*is_integral)() );
对于 4,
template<class...Ts>
bool is_any_of_types( std::any const& a ) {
return (( a.type() == typeid(Ts) ) || ... );
}
在 sizeof...(Ts)
中是线性的。
如果 Ts...
很大,您可能会喜欢散列,但我怀疑它是否足够大。您仍然需要自己枚举类型; is_integral<T>
C++ 语言无法反转
std::any
中存储了一个值,我想知道它是否是整数值(char
、short
、int
、long
、有符号和无符号)或浮点值(float
、double
)或其他值。
如果我只需要检查 int
个值,我会这样做:
std::any a;
if (a.type() == typeid(int)) {
// do some logic for int
}
但是为 C++ 中的所有整数类型做一个巨大的 if (a.type() == typeid(int) || a.type() == typeid(signed char)...)
似乎......不好。
我可以使用 type_traits
中的 is_arithmetic<T>
如果我以某种方式可以访问 T
类型,但我没有,我只有 std::any#type()
而 returns std::type_info
.
有没有办法在 if
条件下没有很多很多析取的情况下完成这个?
(如果它很重要,我正在使用 C++20)
std::any
是类型擦除 class.
它只记住确切的类型,以及转换回那个确切类型的能力(以及如何 copy/move/destroy 它)。
如果您想记住有关存储类型的其他 个事实,您必须自己完成这项工作。
如果不检查确切的 T
,就无法到达 std::any
内的 T
。
一般来说,使用 std::any
将“任何东西”推入其中而无法控制会导致一团糟。 std::any
允许您使用一组“开放”类型来执行此操作,因此您可以安全地将数据从一个代码点传递到另一个代码点,而中间代码不需要知道它是什么。
它无法让您使用未知类型生成类型感知代码。
要解决您的问题,有多种解决方案。
如果您支持的类型集已关闭(以某种方式修复),请使用
std::variant
.如果类型集大部分是封闭的,使用
std::variant< bunch, of, types, std::any >
。然后您可以将“大部分封闭”类型作为variant
处理。如果类型输入可以转换为任何其他类型,则使用阻止转换为std::any
的代码可能是明智的。如果您愿意编写自己的类型擦除,您可以编写自己的或使用额外信息扩充
std::any
。您可以编写一个实用函数来执行大量 if 语句,可能使用模板,时间与类型数量呈线性关系。
对于 1/2,
auto is_integral_f = [](auto&& x){ return std::is_integral<std::decay_t<decltype(x)>>{}; };
std::variant<int,char,unsigned int, long, double, std::any> bob;
bob = 3;
assert( std::visit( is_integral_f, bob ) );
对于 3,
auto is_integral = any_method<bool()>{ is_integral_f };
super_any<decltype(is_integral)> my_any;
my_any bob = 3;
my_any alice = 3.14;
assert( (bob->*is_integral)() );
assert( !(alice->*is_integral)() );
对于 4,
template<class...Ts>
bool is_any_of_types( std::any const& a ) {
return (( a.type() == typeid(Ts) ) || ... );
}
在 sizeof...(Ts)
中是线性的。
如果 Ts...
很大,您可能会喜欢散列,但我怀疑它是否足够大。您仍然需要自己枚举类型; is_integral<T>
C++ 语言无法反转