2010-02-09 21 views
12

I necesita una manera de definir una FLAGS_IF macro (o equivalente) de tal manera que#if 0 como definen

FLAGS_IF(expression) 
<block_of_code> 
FLAGS_ENDIF 

al compilar en depuración (por ejemplo con un modificador de compilador específico) se compila a

if (MyFunction(expression)) 
{ 
    <block_of_code> 
} 

mientras que en la versión no da lugar a ninguna instrucción, tal como lo fue como esto

#if 0 
    <block_of_code> 
#endif 

en mi ignorancia sobre el asunto de C/C++ preprocesadores No se me ocurre ninguna forma ingenua (ya que #define FLAGS_IF(x) #if 0 ni siquiera se compila) de hacer esto, ¿me pueden ayudar?

que necesitan una solución que:

  • no llegar en mal estado si */ está presente en el interior <block_of_code>
  • seguramente generará 0 instrucciones de liberación incluso dentro de las funciones en línea a cualquier profundidad (supongo que esto excluye ? if (false){<block_of_code>} derecha)
  • ¿Es compatible con el estándar si es posible
+4

A no ser que se está compilando en su totalidad y sin optimizaciones, 'si (false) {código}' no ponga nada en la salida. –

+0

Oh, pensé que los compiladores eran menos inteligentes que eso. Gracias – valerio

+10

Como regla general, el compilador es más inteligente que usted. Quizás no ** tú **, pero ciertamente yo. –

Respuesta

12

Lo siguiente debe hacer lo que quiera:

#ifdef DEBUG 
# define FLAGS_IF(x) if (MyFunction((x))) { 
# define FLAGS_ENDIF } 
#else 
# define FLAGS_IF(x) if(0) { 
# define FLAGS_ENDIF } 
#endif 

El Si (0) debe convertirse en ninguna instrucción, o al menos lo hace en la mayoría de los compiladores.

Editar: Hasturkun comentó que realmente no necesita el FLAGS_ENDIF, por lo que tendría lugar escribir el código como el siguiente:

FLAGS_IF(expression) { 
    <block_of_code> 
} 

con las macros siga:

#ifdef DEBUG 
# define FLAGS_IF(x) if (MyFunction((x))) 
#else 
# define FLAGS_IF(x) if(0) 
#endif 
+1

Supongo que valerio está buscando una manera simple de habilitar/deshabilitar más de una función.Su solución no es escalable y oculta la implementación real. La solución para este problema es usar ifdef simple. – eyalm

+0

Si ese es el caso, realmente no necesito una macro FLAGS_IF que oculte la instrucción if. sólo puedo utilizar FLAGS_EXP #define (expresión) 0 si (FLAGS_EXP (expresión)) { } – valerio

2

¿Qué tal algo como esto:

#ifdef DEBUG 
#define FLAGS_IF(expr, block) { if (MyFunction(expr)) block } 
#else 
#define FLAGS_IF(expr, block) 
#endif 

Se puede utilizar la siguiente manera:

FLAGS_IF(your_favourite_expression, 
    ({ 
    // some code 
    }) 
) 
+0

Sí, así es como lo haría – joveha

+1

He hecho esto y la sintaxis resalta los marcadores. Oh bien. – Joshua

+0

Hm, funciona bien en SlickEdit para mí; no he probado muchos otros. –

4

Por qué no puedes usar el siguiente?

 
#ifdef DEBUG 
code for debug mode 
#else 
code for release mode 
#endif 
+0

no me gusta esta, ya que requiere una gran cantidad de código replicación, prefiero poner la lógica de conmutación dentro de la macro – valerio

+0

No tengo muy claro cómo esto es diferente de usar una macro. Ya sea que use #def DEPURACIÓN o use una macro real, parece que va a tener casi la misma cantidad de duplicación. Y usar el #defdef DEPURACIÓN es una forma más común de hacerlo, por lo que es más probable que la gente sepa exactamente lo que está haciendo más rápidamente, en lugar de crear un problema de mantenimiento. – atk

30

macros son bastante malvados, pero no hay nada más malo que ofuscar declaraciones de control y bloques con macros. No hay una buena razón para escribir código como este. Sólo asegúrese de que:

#ifdef DEBUG 
    if (MyFunction(expression)) 
    { 
    <block_of_code> 
    } 
#endif 
+0

estoy totalmente de acuerdo, pero no puedo darse el lujo de hacer esto cada vez. Una macro en este caso es bastante útil – valerio

+2

No creo que esta solución sea diferente a la que usted aceptó en términos de tipeo. –

+0

El otro me permite incluir el #ifdef dentro de la condición – valerio

7

yo podría hacer algo como:

#ifdef DEBUG 
const bool IS_RELEASE_MODE = false; 
#else 
const bool IS_RELEASE_MODE = true; 
#endif 

if (IS_RELEASE_MODE && MyFunction(expression)) 
{ 
    ... 
} 

Esto debe conseguir compilado de versiones de lanzamiento debido al hecho de que si (falso & & f()) es la misma que if (falso), que se optimiza en la mayoría de los compiladores.

Eso es si usted es insistente en no usar #ifdef en el interior de su código. De lo contrario, preferiría la #defdef DEPURACIÓN if (MyFunction (expression)) {...} #endif que otra persona publicó.

+0

Voy a probar esto también – valerio

+0

+1 Definitivamente el forma en que iría Previene el infierno macro y dará como resultado las mismas optimizaciones en la mayoría de los compiladores modernos. – 0xC0DEFACE

3

Por lo general, trato de evitar el uso excesivo de la compilación condicional cuando sea posible.

Por un lado, por lo general es feo y menos legible.

Pero aún más importante, cuando los proyectos usan la compilación condicional para desactivar el código de depuración en &, a veces me he encontrado con problemas de que el código de depuración se queda obsoleto cuando está deshabilitado. Luego, cuando realmente quiera usar el código de depuración, lo enciendo y ... Cosas. No lo hagas Construir. Nunca más.

El código de depuración puede hacer referencia a variables o funciones que ya no existen, o cosas por el código de depuración latentes han cambiado lo suficiente de lo contrario eso es simplemente no es válido sintácticamente más.

Puede ser realmente irritante.

Así que, en lo personal, he evitado la compilación condicional para habilitar/deshabilitar el código de depuración a favor de utilizar una enumeración o macro (que todavía está compilada condicionalmente) para usar como condición en una declaración if. Cuando se compila como if (0), no se genera código de tiempo de ejecución, exactamente como se desee. Sin embargo, el código aún se compila y se comprueba la sintaxis, por lo que siempre es al menos sintácticamente correcto.

#if NDEBUG // using the same standard macro that `assert()` uses 
      // use your own if NDEBUG doesn't make sense 
enum { 
    DebugOn = 0 
} 
#else 
enum { 
    DebugOn = 1 
} 
#endif 


// ... elsewhere 

if (DebugOn) { 
    // this always gets compiled, but if it's a release build 
    // the compiler will not emit anything... 
} 

Como FryGuy mentioned, se puede combinar fácilmente esto con llamar a su MyFunction() si se quiere - en una versión de lanzamiento, la función no será llamado debido a un cortocircuito, que es el comportamiento especificado:

if (DebugOn && MyFunction(expression)) { 
    // this always gets compiled, but if it's a release build 
    // the compiler will not emit anything... 
} 

Pero, personalmente, probablemente me utilizo

if (DebugOn) { 
    if (MyFunction(expression)) { 
     // ... 
    } 
} 

lo que creo que ayuda a llamar un poco más clara (sólo un poco) que este es un Debu bloque g-only.

Esto tiene la ventaja de estar siempre compilado y que no tiene control de flujo escondido detrás de macros (que varias otras respuestas han mencionado como un mal).