Un truco que he visto es usar el &&operador. Dado que un puntero "es verdadero" si no es nulo, puede hacer lo siguiente sin alterar la condición:
assert(a == b &&"A is not equal to B");
Como assertmuestra la condición que falló, también mostrará su mensaje. Si no es suficiente, puede escribir su propia myAssertfunción o macro que mostrará lo que desee.
Otra opción es invertir los operandos y usar el operador de coma. Necesita paréntesis adicionales para que la coma no se trate como un delimitador entre los argumentos:assert(("A must be equal to B", a == b));
Keith Thompson
3
Sin embargo, sería bueno poder imprimir los valores de las variables, como en:assert(a == b && "A (" << A << ") is not equal to B (" << B << ")");
Frank
77
@Frank, printfdevuelve un valor distinto de cero si imprime algo, por lo que podría hacer algo como assert(a == b && printf("a (%i) is not equal to b (%i)", a, b)), aunque en ese momento probablemente debería escribir su propio contenedor de aserción.
zneak
1
Mal código! No entiendo esto! Si a == b es falso, la expresión y también debe ser falsa y, por lo tanto, la cadena no debe evaluarse.
ragnarius
1
@TUIlover, no es así como funcionan los literales de cadena C; son constantes de tiempo de compilación y su uso en este contexto se optimiza trivialmente. No hay costo de tiempo de ejecución.
zneak
45
Otra opción es invertir los operandos y usar el operador de coma. Necesita paréntesis adicionales para que la coma no se trate como un delimitador entre los argumentos:
assert(("A must be equal to B", a == b));
(esto se copió de los comentarios anteriores, para una mejor visibilidad)
Este es un gran enfoque, con un pequeño problema, mostrará "advertencia: el operando izquierdo del operador de coma no tiene ningún efecto" cuando se compila en g ++ con `-Wunused-value
v010dya
1
o con una macro: #ifndef m_assert #define m_assert (expr, msg) afirmar ((msg, expr)) #endif
Szymon Marczak
El uso de un macro wrapper le permite evitar la advertencia de gcc:#define m_assert(expr, msg) assert(( (void)(msg), (expr) ))
Jander
25
Aquí está mi versión de afirmar macro, que acepta el mensaje e imprime todo de manera clara:
Estoy un poco confundida. ¿#Expr se trata como una cadena para la sustitución directa? ¿Cuál es la diferencia entre #Expr y Expr?
Minh Tran
@MinhTran Supongamos que su condición de afirmación es x == y. Luego Expr se expandirá en if( !(x == y))y aquí es donde se verifica la condición, y #Expr se expandirá en cadena literal "x == y", que luego ponemos en el mensaje de error.
Eugene Magdalits
Desafortunadamente, esta solución causa un comportamiento indefinido debido al uso de identificadores reservados.
Puede usar eso directamente o copiar el código de Boost. También tenga en cuenta que la afirmación de Boost es solo un encabezado, por lo que puede tomar ese único archivo si no desea instalar todo Boost.
"Dado que el lector del error de afirmación buscará el archivo y la línea de todos modos desde el mensaje de error", solo si es diligente.
Jason S
Solo si quieren arreglar el error, quieres decir ... qué comentario más tonto
metamorfosis el
1
No. Cuanto más fácil sea que las personas vean el problema, es más probable que tomen medidas.
Jason S
encogerse de hombros En desacuerdo.
metamorfosis
2
afirmar es una combinación macro / función. puede definir su propia macro / función, usando __FILE__, __BASE_FILE__, __LINE__etc, con su propia función que toma un mensaje personalizado
Respuestas:
Un truco que he visto es usar el
&&
operador. Dado que un puntero "es verdadero" si no es nulo, puede hacer lo siguiente sin alterar la condición:Como
assert
muestra la condición que falló, también mostrará su mensaje. Si no es suficiente, puede escribir su propiamyAssert
función o macro que mostrará lo que desee.fuente
assert(("A must be equal to B", a == b));
assert(a == b && "A (" << A << ") is not equal to B (" << B << ")");
printf
devuelve un valor distinto de cero si imprime algo, por lo que podría hacer algo comoassert(a == b && printf("a (%i) is not equal to b (%i)", a, b))
, aunque en ese momento probablemente debería escribir su propio contenedor de aserción.Otra opción es invertir los operandos y usar el operador de coma. Necesita paréntesis adicionales para que la coma no se trate como un delimitador entre los argumentos:
(esto se copió de los comentarios anteriores, para una mejor visibilidad)
fuente
#define m_assert(expr, msg) assert(( (void)(msg), (expr) ))
Aquí está mi versión de afirmar macro, que acepta el mensaje e imprime todo de manera clara:
Ahora puedes usar esto
Y en caso de falla, recibirá un mensaje como este:
Agradable y limpio, siéntase libre de usarlo en su código =)
fuente
x == y
. Luego Expr se expandirá enif( !(x == y))
y aquí es donde se verifica la condición, y #Expr se expandirá en cadena literal"x == y"
, que luego ponemos en el mensaje de error.http://www.boost.org/doc/libs/1_51_0/libs/utility/assert.html
Puede usar eso directamente o copiar el código de Boost. También tenga en cuenta que la afirmación de Boost es solo un encabezado, por lo que puede tomar ese único archivo si no desea instalar todo Boost.
fuente
Como la respuesta de zneak complica un poco el código, un mejor enfoque es simplemente comentar el texto de cadena del que está hablando. es decir.:
Dado que el lector del error de aserción buscará el archivo y la línea de todos modos desde el mensaje de error, verá la explicación completa aquí.
Porque, al final del día, esto:
lee mejor que esto:
en términos de análisis humano del código, es decir. legibilidad. Tampoco es un hack de idiomas.
fuente
afirmar es una combinación macro / función. puede definir su propia macro / función, usando
__FILE__
,__BASE_FILE__
,__LINE__
etc, con su propia función que toma un mensaje personalizadofuente
Para vc, agregue el siguiente código en afirmar.h,
fuente