assert mit Text durch Parameter



  • Hi,

    ich würde cassert gerne aussagekräftiger verwenden. Man erhält ja keine wirkliche Meldung, sondern nur eine Zeilenangabe. Das reicht zwar, es wäre dennoch praktischer, wenn da etwas steht.

    Man kann doch ausnutzen, dass der gesamte Ausdruck angezeigt wird, wenn es zum assert kommt. Folgendes geht z.B.:

    assert(false && "Das ist doch albern.");
    

    Finde ich schon Mal praktisch. Wie macht ihr das gscheit?



  • Braucht man in der Regel nicht. Die Asserts sind nur für den Programmierer gedacht, nicht etwa für den User, dass er eine hübsche Fehlermeldung sieht. Der Programmierer muss zur Behebung des Fehlers sowieso an der entsprechenden Codestelle nachsehen und hat dann auch den passenden Kontext.


  • 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


Log in to reply