assert mit Text durch Parameter


  • Mod

    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


  • Mod

    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 habe

    bb



  • 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


Anmelden zum Antworten