在C++11/14中,是否有“安全”的替代static_cast
的方法,或者实现此功能的库?
所谓“安全”,是指该转换仅应允许不会失去精度的转换。因此,只有当一个数字适合于int32_t
时,才允许从int64_t
到int32_t
的转换,否则将报告错误。
在C++11/14中,是否有“安全”的替代static_cast
的方法,或者实现此功能的库?
所谓“安全”,是指该转换仅应允许不会失去精度的转换。因此,只有当一个数字适合于int32_t
时,才允许从int64_t
到int32_t
的转换,否则将报告错误。
这里有一个gsl::narrow
narrow //
narrow<T>(x)
如果static_cast<T>(x) == x
,则为static_cast<T>(x)
,否则会抛出narrowing_error
static_cast
(以及其他C++样式的强制转换)的预期用途是指示程序员的意图。当您编写auto value = static_cast<int32_t>(value_64);
时,您要表达的是:“是的,我非常*希望*在执行此赋值时将这个值向下转换,可能会截断它。”。因此,编译器(在正常情况下可能会抱怨此转换,例如如果您编写了int32_t value = value_64;
)观察到“好吧,程序员告诉我这就是他们想要的;为什么他们要欺骗我呢?”,并会悄悄编译代码。static_cast
,const_cast
,reinterpret_cast
,并让编译器完成它的工作。编译器有更改警告如何处理的标志(将int64_t
向下转换为int32_t
通常只会导致警告),因此,请确保使用正确的标志将警告强制视为错误。if (i < 256) static_cast<char>(i); else throw bad_cast_exception;
的代码。 - Gavin S. Yancey假设问题是关于编译时检测潜在的有损转换...
一个简单的工具还没有在这里提到,那就是列表初始化不允许缩小,所以你可以写:
void g(int64_t n)
{
int32_t x{n}; // error, narrowing
int32_t g;
g = {n}; // error, narrowing
}
NB. 有些编译器在默认模式下可能会显示“警告”并继续编译这个格式错误的代码,通常你可以通过编译标志来配置这种行为。
你可以使用SFINAE创建自己的模板。以下是一个示例:
template <typename T, typename U>
typename std::enable_if<sizeof(T) >= sizeof(U),T>::type
safe_static_cast(U&& val)
{
return static_cast<T>(val);
}
int main()
{
int32_t y = 2;
std::cout << safe_static_cast<int32_t>(y) << std::endl;
std::cout << safe_static_cast<int16_t>(y) << std::endl; // compile error
}
只有在您转换的大小>=源大小时,才会编译此内容。
请在此处尝试
您可以使用numeric_limits和type_traits来进一步复杂化此过程以处理其他类型。
请注意,我的解决方案是编译时解决方案,因为您询问了static_cast
,其中static指“在编译时确定”。
sizeof(float) < sizeof(int64_t)
,而 b) 不符合原发帖人的要求,即允许将类型转换为较小的类型,但在溢出时抛出运行时错误。 - leftaroundabout
numeric_limits
使得将其实现为一个函数变得非常简单,该函数可以抛出异常或进行运行时断言。 - NathanOliver