assert mit Text durch Parameter
-
my_assert.h
#include <iostream> #include <cstdlib> #ifdef NDEBUG #define ASSERT(cond, message) \ do \ { \ if (!(cond)) \ { \ std::cerr << "Assertion failed at line " \ << __LINE__ << " in " << __FILE__ \ << ":\n" << message << std::endl; \ std::exit(EXIT_FAILURE); \ } \ } \ while(0) #else #define ASSERT(cond, message) do {} while(0)
Ungetestet. Sind bestimmt irgendwo Schreibfehler drin, aber die Idee sollte klar sein.
-
Was ist nochmal schnell der Zweck des do { } while(false) ?
-
semicolon
-
Ethon schrieb:
Was ist nochmal schnell der Zweck des do { } while(false) ?
Das ist eine Erinnerungshilfe, warum Makros gefährlich sind .
Konkret geht es um:
#define makro1() \ zeile1(); \ zeile2(); if (bla) makro1(); // Oh nein! zeile2() ist nun unabhängig vom if! // Jedoch: #define makro2() \ { \ zeile1(); \ zeile2(); \ } if (bla) makro2(); // Oh nein! Das Semikolon macht so das if-else kaputt! else foo();
Das
do ... while(0)
(oder äquivalente Konstrukte) sind daher der "Standard"weg, um Makros funktionsartige Syntax zu geben.
-
Und diese Funktionsartige Syntax braucht jetzt wer?
-
Braucht man doch ständig, z.B. für Funktions-Generatoren oder einfach SeppJs Beispiel oben, um assert abzubilden. Es ist auch praktisch, um Exceptions zu werfen, bei denen man Dateinamen und Zeilennummer mit im Namen haben möchte.
-
mein assert sieht ein wenig anders aus:
namespace my { namespace detail { inline void assert_impl(bool ok, const char* msg, const char* file, const char* fct_name, unsigned int line) { //using cout / endl if(ok) return; cout << "assertion failed (\"" << msg << "\")" << " \r\n" << "\tin file \"" << file << "\": line=" << line << " (function=\"" << fct_name << "\")" << endl; } } } #if defined(NDEBUG) # define assert(x) ((void)0) #else # if defined __GNUC__ # define assert(x) my::detail::assert_impl(x, #x, __FILE__, "unknown", __LINE__) # elif defined MSVC # define assert(x) my::detail::assert_impl(x, #x, __FILE__, __FUNCTION__, __LINE__) # else # define assert(x) my::detail::assert_impl(x, #x, "unknown", "unknown", 0) # endif #endif
wenn ich das für nötig halte, schreib ich das assert trotzdem
assert(param && "bla");
ist aber so selten, dass ich keine extra fct dafür habebb
-
unskilled schrieb:
# if defined __GNUC__ # define assert(x) my::detail::assert_impl(x, #x, __FILE__, "unknown", __LINE__)
Wenn mich nicht alles täuscht, kann der GCC mit
__file__
die aktuelle Funktion ausgeben. Mit Clang geht es 100%ig.
-
Nö, beim GCC ist es auch __FUNCTION__ für die aktuelle Funktion.
C99 introduces __func__, and GCC has provided __FUNCTION__ for a long time. Both of these are strings containing the name of the current function (there are slight semantic differences; see the GCC manual). Neither of them is a macro; the preprocessor does not know the name of the current function. They tend to be useful in conjunction with __FILE__ and __LINE__, though.
http://gcc.gnu.org/onlinedocs/cpp/Standard-Predefined-Macros.html
-
Ich nehme dafür immer BOOST_PRETTY_FUNCTION