Czy istnieje sposób, aby dodać lub edytować wiadomość generowaną przez assert? Chciałbym użyć czegoś takiego
assert(a == b, "A must be equal to B");
Następnie kompilator dodaje linię , czas i tak dalej ...
Czy to możliwe?
Odpowiedzi:
Hack, który widziałem, polega na użyciu &&
operatora. Ponieważ wskaźnik „jest prawdziwy”, jeśli nie jest zerowy, możesz wykonać następujące czynności bez zmiany warunku:
assert(a == b && "A is not equal to B");
Ponieważ assert
pokazuje stan, który się nie powiódł, wyświetli również Twoją wiadomość. Jeśli to nie wystarczy, możesz napisać własną myAssert
funkcję lub makro, które wyświetli, co chcesz.
assert(("A must be equal to B", a == b));
assert(a == b && "A (" << A << ") is not equal to B (" << B << ")");
printf
zwraca wartość niezerową, jeśli coś wypisuje, więc możesz zrobić coś podobnego assert(a == b && printf("a (%i) is not equal to b (%i)", a, b))
, chociaż w tym momencie prawdopodobnie powinieneś napisać własne opakowanie assert.
Inną opcją jest odwrócenie operandów i użycie operatora przecinka. Potrzebujesz dodatkowych nawiasów, aby przecinek nie był traktowany jako separator między argumentami:
assert(("A must be equal to B", a == b));
(to zostało skopiowane z powyższych komentarzy, dla lepszej widoczności)
#define m_assert(expr, msg) assert(( (void)(msg), (expr) ))
Oto moja wersja makra assert, które akceptuje wiadomość i wyświetla wszystko w przejrzysty sposób:
#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();
}
}
Teraz możesz tego użyć
M_Assert(ptr != nullptr, "MyFunction: requires non-null argument");
A w przypadku niepowodzenia otrzymasz taki komunikat:
Assert nie powiodło się: MyFunction: wymaga argumentu innego niż null
Oczekiwano: ptr! = Nullptr
Źródło: C: \ MyProject \ src.cpp, wiersz 22
Ładnie i czysto, możesz użyć go w swoim kodzie =)
x == y
. Następnie Expr rozwinie się do if( !(x == y))
i tutaj sprawdzany jest warunek, a #Expr rozwinie się do literału ciągu "x == y"
, który następnie umieścimy w komunikacie o błędzie.
BOOST_ASSERT_MSG(expre, msg)
http://www.boost.org/doc/libs/1_51_0/libs/utility/assert.html
Możesz użyć tego bezpośrednio lub skopiować kod Boost. Zwróć również uwagę, że potwierdzenie Boost jest tylko nagłówkiem, więc możesz po prostu pobrać ten pojedynczy plik, jeśli nie chcesz instalować całego Boost.
Ponieważ odpowiedź zneak nieco zawija kod, lepszym podejściem jest po prostu skomentowanie tekstu ciągu, o którym mówisz. to znaczy.:
assert(a == b); // A must be equal to B
Ponieważ czytelnik błędu assert i tak odszuka plik i wiersz z komunikatu o błędzie, zobaczy tutaj pełne wyjaśnienie.
Ponieważ pod koniec dnia:
assert(number_of_frames != 0); // Has frames to update
czyta lepiej niż to:
assert(number_of_frames != 0 && "Has frames to update");
pod względem analizy kodu przez człowieka, tj. czytelność. Nie jest to też hack językowy.
assert jest kombinacją makra / funkcji. można zdefiniować własne makro / funkcję, za pomocą __FILE__
, __BASE_FILE__
, __LINE__
itp, z własnej funkcji, które ma niestandardowy komunikat
Możesz także po prostu napisać własną niestandardową funkcję assert. Bardzo prosty przykład:
bool print_if_false(const bool assertion, const char* msg) {
if(!assertion) {
// endl to flush
std::cout << msg << std::endl;
}
return assertion;
}
int main()
{
int i = 0;
int j = 1;
assert(print_if_false(i == j, "i and j should be equal"));
return 0;
}
Twierdzenie brzmi Assertion print_if_false(i == j, "i and j should be equal")
.
W przypadku vc dodaj następujący kod w assert.h,
#define assert2(_Expression, _Msg) (void)( (!!(_Expression)) || (_wassert(_CRT_WIDE(#_Msg), _CRT_WIDE(__FILE__), __LINE__), 0) )