2010-09-11 31 views
88

¿Hay alguna manera de agregar o editar el mensaje arrojado por assert? Me gustaría usar algo como¿Agregar mensajes personalizados en assert?

assert(a == b, "A must be equal to B"); 

A continuación, el compilador añade línea, tiempo y así sucesivamente ...

¿Es posible?

+0

Puede definir una macro, como [esto] (http://stackoverflow.com/a/3767883/1070480). – HelloGoodbye

Respuesta

169

Un truco que he visto es utilizar el operador &&. Desde un puntero "es verdad" si es no nulo, puede realizar las siguientes acciones sin alterar la condición:

assert(a == b && "A is not equal to B"); 

Desde assert muestra la condición de que no, se mostrará el mensaje también. Si no es suficiente, puede escribir su propia función o macro myAssert que mostrará lo que desee.

+4

Jaja! Buena pieza de código. ¡¡Realmente util!! ¡Gracias! – Killrazor

+1

@Killrazor Si le solucionó el problema, considere marcar la respuesta como "aceptada" haciendo clic en la marca de verificación junto a ella. :) – zneak

+15

Otra opción es invertir los operandos y usar el operador de coma. Necesitas paréntesis adicionales para que la coma no se trate como un delimitador entre los argumentos: 'assert ((" A debe ser igual a B ", a == b));' –

1

assert es una combinación de 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

21

Otra opción es invertir los operandos y utilizar el operador coma. Es necesario paréntesis adicionales por lo que la coma no se trata como un delimitador entre los argumentos:

assert(("A must be equal to B", a == b)); 

(esto fue copiado de los comentarios anteriores, para una mejor visibilidad)

+1

Este es un gran enfoque, con un pequeño problema, mostrará "advertencia: el operando izquierdo del operador de coma no tiene efecto" cuando se compila en g ++ con '-Wunused-value – v010dya

+0

o con una macro: #ifndef m_assert #define m_assert (expr, msg) assert ((msg, expr)) #endif –

15
BOOST_ASSERT_MSG(expre, msg) 

http://www.boost.org/doc/libs/1_51_0/libs/utility/assert.html

usted podría usar eso directamente o copiar el código de Boost. También tenga en cuenta que Boost assert es encabezado solamente, por lo que podría tomar ese único archivo si no desea instalar todo Boost.

+0

note boost necesita que implemente la interfaz assert. – Jichao

+0

@Jichao, ¿qué quiere decir con implementar la interfaz assert? – Tarc

-4

para VC, agregue el código siguiente en assert.h,

#define assert2(_Expression, _Msg) (void)((!!(_Expression)) || (_wassert(_CRT_WIDE(#_Msg), _CRT_WIDE(__FILE__), __LINE__), 0)) 
+8

Modificar las cabeceras de su compilador es una mala idea. –

8

como la respuesta de zneak convolutas el código tanto, un mejor enfoque es comentar simplemente el texto de la cadena que está hablando. es decir .:

assert(a == b); // A must be equal to B 

Desde el lector del error afirmar buscará el archivo y la línea de todos modos a partir del mensaje de error, van a ver la explicación completa aquí.

Porque, al final del día, esta:

assert(number_of_frames != 0); // Has frames to update 

lee mejor que esto:

assert(number_of_frames != 0 && "Has frames to update"); 

en términos de análisis sintáctico humana de decir código. legibilidad. Además, no es un hack de idioma.

+0

"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 son diligentes. –

+0

Solo si quieren arreglar el error que quieres decir ... qué comentario tan tonto – metamorphosis

+0

No.Cuanto más fácil le resulte a la gente ver el problema, más probable será que actúe. –

0

¿Por qué nadie mencionó la solución más limpia?

bool AMustBeEqualToB = (a == b); 
assert(AMustBeEqualToB); 
+5

Si no se puede demostrar que la expresión evaluada no tenga efectos secundarios (por ejemplo, una llamada a función), este método obligará al compilador a incluir la evaluación incluso en una compilación de lanzamiento donde las afirmaciones deben ignorarse. Y en cuanto a los "cleannes", qué código se ve mejor es una preferencia personal, pero dudo que mucha gente lo considere más legible que solo un comentario al lado. –

+0

Pero si hacemos un comentario, no se imprimirá en la consola después de que falle la afirmación. –

+0

Sí, eso es cierto, pero, como señalaron los otros, si obtiene una falla de aserción, es muy probable que lo primero que haga sea visitar la línea de código ofensiva. La mayoría de las veces ni siquiera sabrá lo que significa "a" y "b" a menos que observe el contexto en el que falló la afirmación, por lo que debe visitar el código de todos modos. Y si se supone que la aserción es comprensible sin la información del código, entonces para mí sería una indicación de que está utilizando un mecanismo incorrecto de informe de errores en esta situación. –

9

aquí está mi versión de macro afirman, que acepta el mensaje e imprime todo lo que fuera de una manera clara:

#include <iostream> 

#ifndef NDEBUG 
# define M_Assert(Expr, Msg) \ 
    __M_Assert(#Expr, Expr, __FILE__, __LINE__, Msg) 
#else 
# define M_Assert(Expr, Msg) ; 
#endif 

void __M_Assert(const char* expr_str, bool expr, const char* file, int line, const char* msg) 
{ 
    if (!expr) 
    { 
     std::cerr << "Assert failed:\t" << msg << "\n" 
      << "Expected:\t" << expr_str << "\n" 
      << "Source:\t\t" << file << ", line " << line << "\n"; 
     abort(); 
    } 
} 

Ahora, puede utilizar esta

M_Assert(ptr != nullptr, "MyFunction: requires non-null argument"); 

Y en caso de error obtendrá un mensaje como este:

Assert falló: MyFunction: requiere no nulo argumento

esperado: ptr = nullptr

Fuente: C: \ MyProject \ src.cpp, línea 22

agradable y limpio, no dude para usarlo en su código =)

+0

Bueno. Muy útil – Killrazor

+0

Estoy un poco confundido. ¿Se trata a #Expr como una cadena para sustitución directa? ¿Cuál es la diferencia entre #Expr y Expr? –

+0

@MinhTran Supongamos que su condición de afirmación es 'x == y'. Entonces Expr se expandirá a 'if (! (X == y))' y aquí es donde se verificará la condición, y #Expr se expandirá a literal de cadena '" x == y "', que luego pondremos en mensaje de error. –

Cuestiones relacionadas