有 "safe" static_cast 替代方案吗?
Is there a "safe" static_cast alternative?
在 C++11/14 中是否有 "safe" 替代 static_cast
或实现此功能的库?
"safe" 我的意思是转换应该只允许不丢失精度的转换。因此,只有当数字适合 int32_t
时才允许从 int64_t
到 int32_t
的转换,否则会报告错误。
narrow // narrow<T>(x)
is static_cast<T>(x)
if static_cast<T>(x) == x
or it throws narrowing_error
你已经颠倒了用例。
static_cast
(以及其他 c++ 风格的转换)的预期用途是表明程序员的意图。当你写 auto value = static_cast<int32_t>(value_64);
时,你说的是 "Yes, I very much *intend* to downcast this value, possibly truncating it, when I perform this assignment"。结果,编译器在正常情况下可能倾向于抱怨这种转换(比如如果你写了 int32_t value = value_64;
),而是观察到 "well, the programmer has told me that this is what they intended; why would they lie to me?" 并将静默编译代码。
如果您希望 C++ 代码对不安全的转换发出警告或抛出错误,您需要明确地不使用static_cast
、const_cast
、reinterpret_cast
,让编译器完成它的工作。编译器有改变警告处理方式的标志(将 int64_t
向下转换为 int32_t
通常只会导致警告),因此请确保您使用正确的标志来强制将警告视为错误。
您可以使用 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
}
仅当您投射到的大小 >= 源大小时才会编译。
试一试here
您可以使用 numeric_limits for other types and type_traits 进一步复杂化。
注意我的方案是编译时方案,因为你问的是static_cast
,这里的static是指"determined at compile-time".
假设问题是关于潜在有损转换的编译时检测...
这里没有提到的一个简单的工具是列表初始化不允许缩小,所以你可以写:
void g(int64_t n)
{
int32_t x{n}; // error, narrowing
int32_t g;
g = {n}; // error, narrowing
}
注意。某些处于默认模式的编译器可能会显示 "warning" 并继续编译此格式错误的代码,通常您可以通过编译标志配置此行为。
在 C++11/14 中是否有 "safe" 替代 static_cast
或实现此功能的库?
"safe" 我的意思是转换应该只允许不丢失精度的转换。因此,只有当数字适合 int32_t
时才允许从 int64_t
到 int32_t
的转换,否则会报告错误。
narrow //
narrow<T>(x)
isstatic_cast<T>(x)
ifstatic_cast<T>(x) == x
or it throwsnarrowing_error
你已经颠倒了用例。
static_cast
(以及其他 c++ 风格的转换)的预期用途是表明程序员的意图。当你写 auto value = static_cast<int32_t>(value_64);
时,你说的是 "Yes, I very much *intend* to downcast this value, possibly truncating it, when I perform this assignment"。结果,编译器在正常情况下可能倾向于抱怨这种转换(比如如果你写了 int32_t value = value_64;
),而是观察到 "well, the programmer has told me that this is what they intended; why would they lie to me?" 并将静默编译代码。
如果您希望 C++ 代码对不安全的转换发出警告或抛出错误,您需要明确地不使用static_cast
、const_cast
、reinterpret_cast
,让编译器完成它的工作。编译器有改变警告处理方式的标志(将 int64_t
向下转换为 int32_t
通常只会导致警告),因此请确保您使用正确的标志来强制将警告视为错误。
您可以使用 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
}
仅当您投射到的大小 >= 源大小时才会编译。
试一试here
您可以使用 numeric_limits for other types and type_traits 进一步复杂化。
注意我的方案是编译时方案,因为你问的是static_cast
,这里的static是指"determined at compile-time".
假设问题是关于潜在有损转换的编译时检测...
这里没有提到的一个简单的工具是列表初始化不允许缩小,所以你可以写:
void g(int64_t n)
{
int32_t x{n}; // error, narrowing
int32_t g;
g = {n}; // error, narrowing
}
注意。某些处于默认模式的编译器可能会显示 "warning" 并继续编译此格式错误的代码,通常您可以通过编译标志配置此行为。