I have a class for fixed-point arithmetic, of which this is the salient portion:
template <typename I, I S>
struct fixed
{
I value;
fixed(I i) : value(i * S) {}
template <typename J, J T> fixed(const fixed<J, T> &fx)
{
if (S % T == 0)
value = fx.value * (S / T);
else if (T % S == 0)
value = fx.value / (T / S);
else
value = S * fx.value / T;
}
static_assert(S >= 1, "Fixed-point scales must be at least 1.");
};
On GCC 4.4.5, the following line of code:
fixed<int, 8> f = fixed<int, 2>(1);
Generates an error:
fixed.hpp: In constructor ‘fixed<I, S>::fixed(const fixed<J, T>&) [with J = int, J T = 2, I = int, I S = 8]’:
fixed.hpp:81: error: division by zero
Whil开发者_如何转开发e there is a division by constant zero in the code - one of T/S or S/T must be zero for unequal scales - if S%T == 0 (and S is not 0), then S/T is not zero. GCC seems to be doing just enough optimization to figure out that one of my branches is guaranteed to divide by zero, but not enough optimization to figure out that branch guaranteed to not run.
I can throw #pragma GCC diagnostic ignored "-Wdiv-by-zero"
in the file, but that risks masking real warnings.
What's the appropriate way to handle this situation? (Or is my analysis totally wrong and I do have a real runtime division by zero?)
something like?
template<int,int>
struct helper {
static int apply(...) { return S * fx.value / T; }
};
template<int n>
struct helper<0,n> { // need 0,0 as well to avoid ambiguity
static int apply(...) { return fx.value * (S / T); }
};
template<int m>
struct helper<m,0> {
static int apply(...) { return fx.value / (T / S); }
};
helper<(S % T == 0), (T % S == 0)>::apply(...);
or using mpl::bool_
you could "specialize" functions through parameters.
You could use a supporting template to do the division, and specialise it to hardcode an arbitrary value (given it won't be used) when the divisor is 0.
精彩评论