2011-03-07 14 views
8

I tienen una clase para la aritmética de punto fijo, de la que esta es la porción saliente:¿Cómo puedo evitar una advertencia sobre la división por cero en este código de plantilla?

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."); 
}; 

En GCC 4.4.5, la siguiente línea de código:

fixed<int, 8> f = fixed<int, 2>(1); 

genera un 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 

Si bien existe una división por cero constante en el código - uno de T/S o S/T debe ser cero para las escalas desiguales - si S% T == 0 (y S no es 0), entonces S/T no es cero. GCC parece estar haciendo la optimización suficiente para descubrir que una de mis ramas está garantizada para dividir por cero, pero no la optimización suficiente para descubrir que esa rama garantiza que no se ejecutará.

Puedo arrojar #pragma GCC diagnostic ignored "-Wdiv-by-zero" en el archivo, pero eso corre el riesgo de enmascarar las advertencias reales.

¿Cuál es la forma adecuada de manejar esta situación? (¿O mi análisis es totalmente incorrecto y tengo una división de tiempo de ejecución real por cero?)

+0

no es 'fx.value/(T/S); 'lo mismo que' S * fx.value/T' si 'T% S == 0'? – LumpN

+0

http://www.boost.org/doc/libs/1_45_0/libs/mpl/doc/refmanual/eval-if-c.html podría ayudar – Anycorn

+1

Interesante. Probé con VC. const int b = 0; int a = 3/b; /*error*/. const int b = 0; if (b! = 0) int a = 3/b;/* aún error, a veces es solo un problema de compilador tonto .. */ – user534498

Respuesta

7

algo así como?

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(...); 

o usando mpl::bool_ puede "especializar" funciones a través de parámetros.

0

se puede utilizar una plantilla de apoyo para hacer la división, y especializado para codificar un valor arbitrario (dado que no va a utilizar) cuando el divisor es 0.

Cuestiones relacionadas