2010-09-01 10 views
7

que tengo una gran cantidad de código como este:parámetros de plantilla, #define y la duplicación de código

#define WITH_FEATURE_X 

struct A { 
#ifdef WITH_FEATURE_X 
    // ... declare some variables Y 
#endif 
    void f(); 
}; 

void A::f() { 
    // ... do something 
#ifdef WITH_FEATURE_X 
    // ... do something and use Y 
#else 
    // ... do something else 
#endif 
    // ... do something 
} 

y que me gustaría cambiar las #defines con los parámetros de plantilla:

template < int WITH_FEATURE_X > // can be 0 or 1 
struct A; 

Pero I no quiero duplicar casi todo el código de A :: f() para A < 0> :: f() y A < 1> :: f() solo para las pocas líneas que dependen del parámetro. Tampoco quiero llamar a funciones en lugar de los #ifdefs anteriores. ¿Cuál es la solución común?

Respuesta

1

Creo que lo que quiere es un equivalente al comando "static if" que existe en el lenguaje D. Me temo que tal característica no existe en C++.

Tenga en cuenta que si las partes de su código varían en función de la función de su solicitud, estas partes no pertenecen a la función principal porque no son parte del algoritmo desnudo. Entonces la opción de delegar tales funciones en funciones parece buena.

EDITAR
Si sus declaraciones #ifdef se utilizan para hacer lo mismo subtarea de manera diferente, a continuación, definir funciones parciales es lo que hay que hacer. Hará que tu código sea más legible, no menos.

Si se utilizan para acciones completamente diferentes, bueno, su código ya está desordenado. Haz algo al respecto.

En cuanto al problema de rendimiento que teme que aparezca, confíe en su compilador.

Edit2
me olvidó mencionar que la respuesta a la primera parte de su código: utilizar el siguiente truco para añadir o eliminar miembros en función de "característica".

namespace helper 
{ 
    template<int feature> 
    struct A; 

    template<> 
    struct A<0> { // add member variables for case 0 }; 

    template<> 
    struct A<1> { // add member variables for case 1 }; 
} 

template<int feature> 
class A : private helper::A<feature> 
{ 
    // ... functions here 
}; 
+0

Sí, algo similar a "estática si" parece ser necesario. Tal vez eso es posible en este caso con las plantillas boost (como enable_if)? Me temo que las funciones llenan el código mucho, habría llamadas anidadas, y el código se volvería bastante artificial, ilegible y quizás menos optimizado para la velocidad. – Thomas

+0

Esa es una buena idea con helper :: A! Voy a tratar de recodificar algunos #ifdefs con funciones y tu truco más tarde y ver si me gusta el res ult. – Thomas

0

La solución común, es simplemente usar #ifdef me temo. :-)

0

No entiendo el punto de la duplicación de código común. Si está utilizando el parámetro de la plantilla, simplemente está reemplazando su #ifdef con if (WITH_FEATURE_X). ¿Estás hablando de código inflado por el compilador. Como está tratando de reemplazar #ifdef, supongo que utilizará A < 0> o A < 1> en cualquier punto. Así que no veo una compilación de código ni siquiera por el compilador.

2

Si se quiere evitar la duplicación de la lógica de la función f puede utilizar el template method pattern (no, no es ese tipo de template.

template <bool enabled> 
class helper { 
protected: 
    void foo() { /* do nothing */ } 
}; 

template <> 
class helper<true> { 
protected: 
    Y y; 
    void foo() { /* do something with y */ } 
}; 

struct A : private helper<WITH_FEATURE_X> { 
    void f() { 
     // common stuff 

     foo(); // optimized away when WITH_FEATURE_X is false 

     // more common stuff 
    } 
}; 
+0

Parece ser la misma sugerencia que la de Benoît, pero es bueno saber el nombre del patrón y ver cómo se aplica a las funciones. Gracias. – Thomas

Cuestiones relacionadas