C++ static_cast with assert
c++
Solution
No macro needed, you can simply use preprocessor conditionals inside the function body:
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;
}
and
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;
}
Then use
long l = debug_checked_coercion<long>(ll);
Notice that I've minimized the use of `static_cast`, since it isn't needed for narrowing numeric conversions.
Problem
Unfortunately, I have to perform a narrowing cast when calling a 3rd party library. I don't want to impose an overhead in my release build, so will be using a static_cast. However, it's an array index so could lead to some entertainment if it ends up negative. Is there some way to create a safe cast in debug mode only that will check the value to ensure there is no loss during the cast? The only way I can think of is to use macros, and I'd rather not. For example, in both release and debug mode using 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"; } ``` results in the output: ``` 2147483648 -2147483648 ``` Using a macro: ``` 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"; } } ``` results in the same output in release mode, but the following in debug: ``` 2147483648 ERROR: Naughty cast ``` Any better options? NB: I'm disregarding the entertainment we might enjoy from an array large enough to cause this issue, and perhaps this is simply over-paranoid, but I imagine the concept may have applications other than my specific requirement.