不幸的是,我必须在调用第三方库时执行缩小演员。我不想在我的发布版本中施加开销,因此将使用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";
}
导致输出:
2147483648
-2147483648
使用宏:
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";
}
}
在发布模式下产生相同的输出,但调试中的以下内容:
2147483648
ERROR: Naughty cast
有更好的选择吗?
注意:我忽略了我们可能从一个足以引起这个问题的阵列中获得的娱乐,也许这只是过度偏执,但我想这个概念可能有我的特定要求以外的应用程序。
答案 0 :(得分:7)
不需要宏,只需在函数体内使用预处理器条件:
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;
}
和
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;
}
然后使用
long l = debug_checked_coercion<long>(ll);
请注意,我已尽量减少static_cast
的使用,因为缩小数字转换并不需要。
答案 1 :(得分:0)
我倾向于同意dlf,如果它足够重要,可以在Debug中抛出异常,那么你应该也可以在Release中这样做。
如果我选择了有时会崩溃的高效代码,而且效率稍低的代码并不知道我会选择什么。
保罗。