I am doing a bunch of applied-mathematics/signal-processing/algorithms C++ code.
I have enabled the -Wconversion
compiler warning to catch issues like runtime conversion of numbers that are type double
to type int32_t
.
Obviously I am always concerned during these conversions because:
int32_t
in this case))Whenever I am concerned about such a conversion I usually use the one-liner check:
boost::numeric_cast<DestType>(SourceType)
However I would like to do the same thing without boost
.
Does straight C++ have an equivalent boost::numeric_cast<DestType>(SourceType)
?
If straight C++ does not have an equivalent, what would be a comparable non-boost
implementation?
I would think a somewhat comparable check would be basically a template function that has a single if statement to check the input parameter against positive or negative overflow (by using the std::numeric_limits<DestType>
::max()
and ::min()
and throws an exception).
As @SergeyA stated, no the standard C++ spec does not currently have an equivalent to Boost's boost::numeric_cast<typename Destination>(Source value)
.
Here is a straight-forward implementation that uses only standard C++:
template<typename Dst, typename Src>
inline Dst numeric_cast(Src value)
{
typedef std::numeric_limits<Dst> DstLim;
typedef std::numeric_limits<Src> SrcLim;
const bool positive_overflow_possible = DstLim::max() < SrcLim::max();
const bool negative_overflow_possible =
SrcLim::is_signed
or
(DstLim::lowest() > SrcLim::lowest());
// unsigned <-- unsigned
if((not DstLim::is_signed) and (not SrcLim::is_signed)) {
if(positive_overflow_possible and (value > DstLim::max())) {
throw std::overflow_error(__PRETTY_FUNCTION__ +
std::string(": positive overflow"));
}
}
// unsigned <-- signed
else if((not DstLim::is_signed) and SrcLim::is_signed) {
if(positive_overflow_possible and (value > DstLim::max())) {
throw std::overflow_error(__PRETTY_FUNCTION__ +
std::string(": positive overflow"));
}
else if(negative_overflow_possible and (value < 0)) {
throw std::overflow_error(__PRETTY_FUNCTION__ +
std::string(": negative overflow"));
}
}
// signed <-- unsigned
else if(DstLim::is_signed and (not SrcLim::is_signed)) {
if(positive_overflow_possible and (value > DstLim::max())) {
throw std::overflow_error(__PRETTY_FUNCTION__ +
std::string(": positive overflow"));
}
}
// signed <-- signed
else if(DstLim::is_signed and SrcLim::is_signed) {
if(positive_overflow_possible and (value > DstLim::max())) {
throw std::overflow_error(__PRETTY_FUNCTION__ +
std::string(": positive overflow"));
} else if(negative_overflow_possible and (value < DstLim::lowest())) {
throw std::overflow_error(__PRETTY_FUNCTION__ +
std::string(": negative overflow"));
}
}
// limits have been checked, therefore safe to cast
return static_cast<Dst>(value);
}
notes:
std::numeric_limits<float>::min()
but instead must use std::numeric_limits<Dst>::lowest()
because ::min
returns is 1e-38 instead of a negative floating point valuestd::numeric_limits
are const expressions and so the compiler will be able to greatly simplify this at compile time (i.e. N if statements will be reduced to one if-statement at compile time or none)If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With