#define mit do{...}while(0) obsolet: Neu mit Lamdas!



  • Ich persönlich brauche auch nicht den do-while-Trick bei Makros.
    Es gibt bei mir nämlich nur zwei Arten von Makros.
    Einmal die Meta-Makros zur Codegenerierung mehrerer ähnlich aussehender Funktion (was allerdings nicht durch Templates lösbar ist...) und dann Diagnostics-Makros wo ich nur Makros verwende, weil ich an die Funktions- und Dateinamen kommen will.
    Im ersteren ist das egal, beim Zweiten ist das eh nur ein einfacher Funktionsauruf.


  • Mod

    Einmal die Meta-Makros zur Codegenerierung mehrerer ähnlich aussehender Funktion

    Beispiel bitte. 👍

    Ich glaube das auch schon mal gebraucht zu haben, aber ich bin gerade im "kann man bestimmt Widerlegen-Rausch". 😃



  • @dersinndeslambdas
    Hast du mal probiert ob aktuelle Compiler das auch vernünftig optimieren können?



  • Arcoth schrieb:

    Einmal die Meta-Makros zur Codegenerierung mehrerer ähnlich aussehender Funktion

    Beispiel bitte. 👍

    Ich glaube das auch schon mal gebraucht zu haben, aber ich bin gerade im "kann man bestimmt Widerlegen-Rausch". 😃

    Das stammt aus meiner eigenen Implementierung einer iostream-Bibliothek*, genau genommen aus der Implementierung zum Pendant von std::num_put:

    #define MY_IMPL_WRITE_INTEGRAL_DIGITS(NAME, BASE) \
    template <typename IntegralT, typename OIterator, class Encoding> \
    void write_integral_digits_##NAME(IntegralT value, OIterator &iter, \
                                      const numeric<Encoding> &numeric_info) \
    { \
        streamsize num_digits = 0; \
        do \
        { \
            print_code_point(iter, numeric_info.digit_to_char(value % BASE)); \
            value /= BASE; \
            if (value > 0 && numeric_info.is_##NAME##_sep_after(num_digits++)) \
                print_code_point(iter, numeric_info.NAME##_sep()); \
        } while (value > 0); \
    }
    
    MY_IMPL_WRITE_INTEGRAL_DIGITS(decimal, 10)
    MY_IMPL_WRITE_INTEGRAL_DIGITS(hexadecimal, 16)
    MY_IMPL_WRITE_INTEGRAL_DIGITS(octal, 8)
    
    #undef MY_IMPL_WRITE_INTEGRAL_DIGITS
    

    edit:
    Ach ja, übrigens:
    https://github.com/Arcoth/VTMPL/blob/master/algorithms.hxx

    #define DEFINE_FO( name, ... ) \
    template<index_type a> \
    struct name \
    { \
    template<index_type b> \
    struct function : std::integral_constant<index_type, (__VA_ARGS__)> {}; \
    }
    
    DEFINE_FO(add, b + a);
    DEFINE_FO(xor_, b xor a);
    DEFINE_FO(multiply, b * a);
    DEFINE_FO(modulo, b % a);
    
    #undef DEFINE_FO
    #define DEFINE_FO( name, ... ) \
    template<index_type a> struct name : std::integral_constant<index_type, (__VA_ARGS__)> {}
    
    DEFINE_FO( square, a*a );
    DEFINE_FO( invert, -a );
    #undef DEFINE_FO
    

    /edit

    *Ja, ich habe sonst nichts zu tun. Deshalb implementiere ich quasi die komplette Standardbibliothek neu und "besser" (vom Design her). Vieles sind einfach nur Wrapper (mein std::vector z.B., nur an mein Iterator-Konzept angepasst und mit meinem Errorchecking), anderes habe ich komplett implementiert. Darunter auch der komplette IO-Teil. Meine Implementierung hat eine kleinere Hierachie, ist nicht ganz so konfigurierbar, einfacher zu nutzen sowohl was Manipulatoren als auch streambufs angeht, Multibyteencoding-aware und formattiert Integer ganze 20ns schneller als die Implementierung meines Compilers ( 😃 ).


  • Mod

    numeric_info.is_##NAME##_sep_after(num_digits++)

    Warum ist is_##NAME##_sep_after fest für alle Basen einzeln definiert? Warum kein Template, dass die Basis als Template-Argument nimmt?



  • Arcoth schrieb:

    numeric_info.is_##NAME##_sep_after(num_digits++)

    Warum ist is_##NAME##_sep_after fest für alle Basen einzeln definiert? Warum kein Template, dass die Basis als Template-Argument nimmt?

    virtual Memberfunction.



  • Warum es nicht wie alle normalen Menschen machen und die Basis als Funktionsparameter übergeben?


  • Mod

    Ach ja, übrigens:
    https://github.com/Arcoth/VTMPL/blob/master/algorithms.hxx

    Da haste mich glatt mit meinem eigenen Code erwischt. 👍

    (VTMPL muss ich mal wieder auffrischen, mach' mich dran)



  • warbat schrieb:

    Warum es nicht wie alle normalen Menschen machen und die Basis als Funktionsparameter übergeben?

    Ich hatte vorschnellen Optimierungswahn und wollte ifs vermeiden.
    Eine Art Tag-Dispatching wäre allerdings ok, aber jetzt ist es zu spät.



  • dersinndeslambdas schrieb:

    Jeder Code hat immer mal wieder ein

    #define FOO(x) do { ... } while(0)
    

    drin.

    oder ähnliche Schreibweisen. gcc erzwingt irgendwie while(0){}, weil er in allen anderen Schreibweisen rumwarnt.

    dersinndeslambdas schrieb:

    Heute kam mir ein Geistesblitz: Man kann neu Lambdas verwenden!

    #define FOO(x) ((void)([](){ ... })())
    

    Es ist sogar möglich, Werte zurückzugeben:

    #define FOO(x) ([](){ ... return ... }())
    

    Jetzt kann man Makros endlich mit einem Komma-Operator verwenden:

    for (...)
      FOO(x), FOO(y); // ging vorher nicht
    

    Was haltet ihr davon? 👍

    Sehr gute Idee! 👍
    Nun paßt __asm int 3; ins ASSERT und es bleibt ein Ausdruck.


Anmelden zum Antworten