Zähl-Makro?



  • Sone schrieb:

    Solche COUNT-Funktionen gehen nicht ohne den aktuellen Wert. Da müsste intern etwas erhöht werden, aber das ist nicht möglich, da zur Compilezeit nur Konstanten existieren.

    Da geht immer was.
    Eisflamme ist sicherlich nicht drauf festgelegt, wie es aufzurufen ist.
    Vielleicht

    MAKE_FLAGS(FILE,FILE_READ,FILE_WRITE,FILE_COPY_ON_WRITE,FILE_SEQUENTIAL,FILE_TEMPORARY)
    

    oder irgendwas anderes Spaßiges.



  • __LINE__ ändert sich.

    Also __LINE__ - 34.
    Dann muss das ganze in eine Separate Header-Datei. Wenn das nämlich in einer größeren ist, und jemand nicht Bescheid weiß dass nach jedem Ändern des Quelltexts diese eine magic-constant geändert werden muss, dann gibt das Ärger.

    Eisflamme, du Faulpelz 🤡



  • würde an deiner stelle das mit den makros komplett lassen und konstanten benützen,
    da es einfach typensicher ist



  • Ich verstehe auch nicht, was das define mit ner Zahl bringt, dafür will ich ja Konstanten nutzen.

    Das mit __LINE__ ist klug, ich verstehe aber den Einwand nicht:

    #define LE_VALUE __LINE__ - 34
    
    const unsigned int VALUE1 = 2 << LE_VALUE; // MUST BE LINE NUMBER XY!!
    const unsigned int VALUE2 = 2 << LE_VALUE;
    

    Das gefällt mir super. 😋



  • Sone schrieb:

    __LINE__ ändert sich.

    Also __LINE__ - 34.
    Dann muss das ganze in eine Separate Header-Datei. Wenn das nämlich in einer größeren ist, und jemand nicht Bescheid weiß dass nach jedem Ändern des Quelltexts diese eine magic-constant geändert werden muss, dann gibt das Ärger.

    Eisflamme, du Faulpelz 🤡

    Leider klappt folgendes nicht auf jedem Compiler:

    #define LINESTART __LINE__
    #define FILE_READ (1<<(__LINE__-LINESTART))
    #define FILE_WRITE (1<<(__LINE__-LINESTART))
    #define FILE_COPY_ON_WRITE (1<<(__LINE__-LINESTART))
    #define FILE_SEQUENTIAL (1<<(__LINE__-LINESTART))
    #define FILE_TEMPORARY (1<<(__LINE__-LINESTART))
    

    LINESTART ist dann auf machen als 34 definiert und auf manchen als __LINE__ definiert.



  • __LINE__ mag nett erscheinen, bis jemand mal auf die Idee kommt, zu gruppieren oder Kommentare einzufügen. Als ob Leute ständig nachfolgenden Code prüfen würden, wenn sie irgendwo eine Zeile einfügen.

    Sowas ist extrem heikel -- und kann zu qualvoller Bugsuche führen, weil niemand das Problem hier vermutet. Das Risiko wäre mir die minimale Schreibaufwandersparnis definitiv nicht wert. Dann schon eher was in Richtung Boost.Preprocessor...



  • Nexus schrieb:

    Dann schon eher was in Richtung Boost.Preprocessor...

    Und das wäre Overkill für so ein lächerliches Problem.

    volkard schrieb:

    Leider klappt folgendes nicht auf jedem Compiler:

    Hab schon Probiert. 😉



  • Eisflamme schrieb:

    Das mit __LINE__ ist klug, ich verstehe aber den Einwand nicht:

    Was, wenn diese PP-Direktive auf einmal nicht mehr in Zeile 34, sondern 35 ist?


  • Mod

    #include <boost/preprocessor/seq/for_each.hpp>
    #include <boost/preprocessor/variadic/to_seq.hpp>
    
    #define DEF_VALUE( num, data, name ) const unsigned name = 1 << ( num - 2 );
    
    #define DEF_VALUES( ... ) BOOST_PP_SEQ_FOR_EACH( DEF_VALUE, _, BOOST_PP_VARIADIC_TO_SEQ( __VA_ARGS__ ) )
    
    DEF_VALUES( FILE_READ, FILE_WRITE, FILE_COPY_ON_WRITE, FILE_SEQUENTIAL, FILE_TEMPORARY )
    


  • Das sieht gut aus! Klappt das auch ohne Vartemps im Compiler?



  • Was sind Vartemps?



  • Variadische Templates braucht das nicht, aber variadische Makros, die einige Compiler (*hust* MSVC *hust*) nicht so richtig beherrschen. Du kannst aber auch direkt eine Boost.PP-Sequenz benutzen:

    #include <boost/preprocessor/seq/for_each.hpp>
    
    #define DEF_VALUE( num, data, name ) const unsigned name = 1 << ( num - 2 );
    
    #define DEF_VALUES(seq) BOOST_PP_SEQ_FOR_EACH( DEF_VALUE, _, seq)
    
    DEF_VALUES( (FILE_READ) (FILE_WRITE) (FILE_COPY_ON_WRITE) (FILE_SEQUENTIAL) (FILE_TEMPORARY) )
    

    Sieht nicht ganz so hübsch aus, aber läuft.



  • volkard schrieb:

    Leider klappt folgendes nicht auf jedem Compiler:

    #define LINESTART __LINE__
    #define FILE_READ (1<<(__LINE__-LINESTART))
    #define FILE_WRITE (1<<(__LINE__-LINESTART))
    #define FILE_COPY_ON_WRITE (1<<(__LINE__-LINESTART))
    #define FILE_SEQUENTIAL (1<<(__LINE__-LINESTART))
    #define FILE_TEMPORARY (1<<(__LINE__-LINESTART))
    

    LINESTART ist dann auf machen als 34 definiert und auf manchen als __LINE__ definiert.

    Compiler, auf denen das nicht klappt, implementieren Makros richtig. Makros werden erst im Body expandiert.



  • volkard schrieb:

    Leider klappt folgendes nicht auf jedem Compiler:

    #define LINESTART __LINE__
    #define FILE_READ (1<<(__LINE__-LINESTART))
    #define FILE_WRITE (1<<(__LINE__-LINESTART))
    #define FILE_COPY_ON_WRITE (1<<(__LINE__-LINESTART))
    #define FILE_SEQUENTIAL (1<<(__LINE__-LINESTART))
    #define FILE_TEMPORARY (1<<(__LINE__-LINESTART))
    

    LINESTART ist dann auf machen als 34 definiert und auf manchen als __LINE__ definiert.

    Was spricht gegen:

    constexpr std::size_t LINESTART = __LINE__;
    

    ?



  • Nathan schrieb:

    volkard schrieb:

    Leider klappt folgendes nicht auf jedem Compiler:

    #define LINESTART __LINE__
    #define FILE_READ (1<<(__LINE__-LINESTART))
    #define FILE_WRITE (1<<(__LINE__-LINESTART))
    #define FILE_COPY_ON_WRITE (1<<(__LINE__-LINESTART))
    #define FILE_SEQUENTIAL (1<<(__LINE__-LINESTART))
    #define FILE_TEMPORARY (1<<(__LINE__-LINESTART))
    

    LINESTART ist dann auf machen als 34 definiert und auf manchen als __LINE__ definiert.

    Was spricht gegen:

    constexpr std::size_t LINESTART = __LINE__;
    

    ?

    Gut.
    Dann muss man die anderen aber auch alle mit constexpr machen und hat gar kein #define mehr.

    Hmm, wenn wir soweit gehen, tuts ja sogar ein enum.

    #include <iostream>
    
    enum FILEMODE{
        LINESTART = __LINE__,
        FILE_READ = (1<<(__LINE__-LINESTART-1)),
        FILE_WRITE = (1<<(__LINE__-LINESTART-1)),
        FILE_COPY_ON_WRITE = (1<<(__LINE__-LINESTART-1)),
        FILE_SEQUENTIAL = (1<<(__LINE__-LINESTART-1)),
        FILE_TEMPORARY = (1<<(__LINE__-LINESTART-1)),
    };
    
    int main(){
        std::cout<<FILE_WRITE<<'\n';
        std::cout<<FILE_READ<<'\n';
    }
    

    oder

    #include <iostream>
    
    #define BEGINFLAGS _line_start = __LINE__
    #define NEXTFLAG (1<<(__LINE__-_line_start-1))
    
    enum file_mode{
        BEGINFLAGS,
        read = NEXTFLAG,
        write = NEXTFLAG,
        copy_on_write = NEXTFLAG,
        sequential = NEXTFLAG,
        temporary = NEXTFLAG,
    };
    
    int main(){
        std::cout<<file_mode::write<<'\n';
        std::cout<<file_mode::read<<'\n';
    }
    


  • Selbst wenn man das noch mit einer Enumeration hinschustert, finde ich das hässlich. Wieso nicht einfach direkt hinschreiben... alles andere ist doch Overkill.



  • enum FILEMODE{ 
        LINESTART = __LINE__, 
        FILE_READ = (1<<(__LINE__-LINESTART-1)), 
        FILE_WRITE = (1<<(__LINE__-LINESTART-1)), 
        FILE_COPY_ON_WRITE = (1<<(__LINE__-LINESTART-1)), 
        FILE_SEQUENTIAL = (1<<(__LINE__-LINESTART-1)), 
        FILE_TEMPORARY = (1<<(__LINE__-LINESTART-1)), 
    }; 
    
    // vs
    
    enum FILEMODE
    { 
        FILE_READ = 1, 
        FILE_WRITE = 1 << 1, 
        FILE_COPY_ON_WRITE = 1 << 2, 
        FILE_SEQUENTIAL = 1 << 3, 
        FILE_TEMPORARY = 1 << 4 
    };
    

Anmelden zum Antworten