不幸的是,我必须在调用第三方库时执行缩小演员.我不想在我的发布版本中施加开销,因此将使用static_cast.然而,它是一个数组索引,如果它最终消极,可能导致一些娱乐.有没有办法在调试模式下创建一个安全的强制转换,它会检查值以确保在转换过程中没有丢失?我能想到的唯一方法是使用宏,而我宁愿不这样做.
例如,在使用MSVC的发布和调试模式下:
int main() {
long long ll = std::numeric_limits<long>::max();
++ll;
std::cout << ll << "\n";
long l = static_cast<long>(ll);
std::cout << l << "\n";
}
Run Code Online (Sandbox Code Playgroud)
结果输出:
2147483648
-2147483648
Run Code Online (Sandbox Code Playgroud)
使用宏:
template<class to, class from>
to checked_static_cast(const from& from_value) {
to to_value = static_cast<to>(from_value);
if (static_cast<from>(to_value) != from_value)
throw std::runtime_error("Naughty cast");
return to_value;
}
#ifdef _DEBUG
#define debug_checked_static_cast(to, val) checked_static_cast<to>(val)
#else
#define debug_checked_static_cast(to, val) static_cast<to>(val)
#endif
int main() {
try {
long long ll = std::numeric_limits<long>::max();
++ll;
std::cout << ll << "\n";
long l = debug_checked_static_cast(long, ll);
std::cout << l << "\n";
} catch (const std::exception& e) {
std::cerr << "ERROR: " << e.what() << "\n";
}
}
Run Code Online (Sandbox Code Playgroud)
在发布模式下产生相同的输出,但在调试中如下:
2147483648
ERROR: Naughty cast
Run Code Online (Sandbox Code Playgroud)
有更好的选择吗?
注意:我无视我们可能从一个足以引起这个问题的阵列中获得的娱乐,也许这只是过度偏执,但我想这个概念可能有我的特定要求以外的应用.
不需要宏,只需在函数体内使用预处理器条件:
template<class to, class from>
inline to debug_checked_static_cast(const from& from_value) {
to to_value{static_cast<to>(from_value)};
#if _DEBUG
from round_trip{to_value};
if (round_trip != from_value)
throw std::runtime_error("Naughty cast");
#endif
return to_value;
}
Run Code Online (Sandbox Code Playgroud)
和
template<class to, class from>
inline to debug_checked_coercion(const from& from_value) {
to to_value{from_value};
#if _DEBUG
from round_trip{to_value};
if (round_trip != from_value)
throw std::runtime_error("Naughty cast");
#endif
return to_value;
}
Run Code Online (Sandbox Code Playgroud)
然后用
long l = debug_checked_coercion<long>(ll);
Run Code Online (Sandbox Code Playgroud)
请注意,我已经最小化了使用static_cast,因为缩小数字转换不需要它.