Un método más bonita:
#ifdef _DEBUG
#define DBOUT cout // or any other ostream
#else
#define DBOUT 0 && cout
#endif
DBOUT << "This is a debug build." << endl;
DBOUT << "Some result: " << doSomething() << endl;
Mientras usted no hace nada raro, las funciones de llamada y pasada a DBOUT
no serán llamados en las versiones de lanzamiento. Esta macro funciona debido a la precedencia del operador y al AND lógico; porque &&
tiene una prioridad menor que <<
, compilaciones de versiones compila DBOUT << "a"
como 0 && (cout << "a")
. El AND lógico no evalúa la expresión de la derecha si la expresión de la izquierda se evalúa como cero o false
; debido a que la expresión de la mano izquierda siempre se evalúa como cero, la expresión de la mano derecha siempre es eliminada por cualquier compilador que valga la pena usar, excepto cuando toda la optimización está desactivada (e incluso entonces, el código obviamente inalcanzable puede ignorarse).)
Aquí es un ejemplo de las cosas extrañas que rompan esta macro:
DBOUT << "This is a debug build." << endl, doSomething();
Ver las comas. doSomething()
siempre se llamará, independientemente de si se define _DEBUG
o no. Esto se debe a que la declaración se evalúa en las versiones de lanzamiento como:
(0 && (cout << "This is a debug build." << endl)), doSomething();
// evaluates further to:
false, doSomething();
Para utilizar comas con esta macro, la coma debe ser envuelto en paréntesis, así:
DBOUT << "Value of b: " << (a, b) << endl;
Otro ejemplo:
(DBOUT << "Hello, ") << "World" << endl; // Compiler error on release build
En las versiones de lanzamiento, esto se evalúa como:
(0 && (cout << "Hello, ")) << "World" << endl;
// evaluates further to:
false << "World" << endl;
que causa un error de compilación porque bool
no se puede desplazar a la izquierda mediante un puntero char
a menos que se haya definido un operador personalizado. Esta sintaxis también causa problemas adicionales:
(DBOUT << "Result: ") << doSomething() << endl;
// evaluates to:
false << doSomething() << endl;
al igual que cuando se utiliza la coma mal, doSomething()
todavía es llamado, ya que su resultado tiene que ser pasado al operador de izquierda-turno. (Esto sólo puede ocurrir cuando un operador personalizada se define que la izquierda se desplaza un bool
por un puntero char
;. De lo contrario, se produce un error de compilación)
No DBOUT << ...
un paréntesis. Si quiere poner en paréntesis un cambio de enteros literal, entonces entre paréntesis, pero no conozco una sola buena razón para poner en paréntesis un operador de flujo.
¡Gracias! Estaba empezando a pensar algo así y me alegra ver que no soy el único que lo estaba pensando. Lo probaré el lunes en el trabajo y veré qué tan bien el compilador puede optimizar la transmisión. – Emanuel
Cualquiera que use este método, tenga en cuenta que algunos elementos no se optimizarán en el modo de lanzamiento. Si tiene: '' 'debug << someCPUIntensiveFunctionOrFunctionWhichMayAffectState() <<" \ n "' '' aún se ejecutará en modo de lanzamiento. Me perdí este cavet la primera vez –