13.10.2022 07:34 JiiPee kirjutas:
> On 13/10/2022 00:37, Paavo Helde wrote:
>> wouldn't use static_cast here, but e.g. boost::numeric_cast,
>
> OK, interesting option.
>
> Ok, but you would always cast it somehow and not for example create some
> conversion function etc?
>
> I mean, if this conversion is needed in 500 places, you would just add
> that boost::numeric_cast (or some other cast) into these places?
boost::numeric_cast is technically a function, not a cast.
>
> It makes the code quite "long" and a little difficult to read if adding
> a lot of casts... but maybe its the only way.
Right. In real code I'm using my own checked_cast and debug_cast, which
names I consider reasonable readable and greppable. These are a bit
involved because the boost::numeric_cast did not always quite do what we
wanted exactly, but for brevity I leave out these details from here.
template<typename T, typename U>
inline constexpr T checked_cast(U x) {
// Some code to avoid false alarms on MS "smaller type check.
// ...
// Some code to refuse converting NaN to uint64
// ...
return boost::numeric_cast<T, U>(x);
}
// A specialization for double->float conversion
// to avoid false alarm on -inf, and to allow converting
// large finite double values to float inf.
template<>
inline constexpr float checked_cast<float, double>(double x) {
return static_cast<float>(x);
}
template<typename T, typename U>
inline constexpr T debug_cast(U x) {
#ifdef NDEBUG
return static_cast<T>(x);
#else
return checked_cast<T,U>(x);
#endif
}
I'm using debug_cast whenever I am quite sure the cast should always
work, and checked_cast if there is any doubt.