coolste Makros



  • Hab ein leichtes Jucken bei den beiden for, ganz leicht, fast nicht wahrnehmbar

    Kellerautomat schrieb:

    #define synchronized(mtx) \
        for(bool _once = true; _once; _once = false) \
            for(std::lock_guard<typename std::remove_reference<decltype(mtx)>::type> _guard(mtx); _once; _once = false)
    

    Wäre es nicht direkter mit

    #define synchronized(mtx) \
        if(bool _never = false) \ 
           ;
        else \
            for(std::lock_guard<typename std::remove_reference<decltype(mtx)>::type> _guard(mtx); !_never; _never = true)
    

    ?



  • Also der uralte MSVC ist mir relativ egal - vor allem, da ich MSVC gar nicht benutze 😉

    Edit: Aber man koennte es natuerlich so machen:

    #define synchronized(mtx) \
        if(bool _once = true) \
            for(std::lock_guard<typename std::remove_reference<decltype(mtx)>::type> _guard(mtx); _once; _once = false)
    

    Allerdings bestuende dann die 'Gefahr' einer Compilerwarning.



  • Kellerautomat schrieb:

    Also der uralte MSVC ist mir relativ egal - vor allem, da ich MSVC gar nicht benutze 😉

    Nein, nicht deswegen, nicht um es mit uraltem MSVC zu benutzen, sondern damit selbst der dümmste Standard-Compiler mehr zum Optimieren sieht, weniger Sprünge direkt anlegt vor dem Optimierungslauf.
    Das zweifache "_once = false" machte mich stutzig.



  • Das ist dafuer da, falls jemand break; benutzt, um rauszuspringen 😉



  • Kellerautomat schrieb:

    Also der uralte MSVC ist mir relativ egal - vor allem, da ich MSVC gar nicht benutze 😉

    Edit: Aber man koennte es natuerlich so machen:

    #define synchronized(mtx) \
        if(bool _once = true) \
            for(std::lock_guard<typename std::remove_reference<decltype(mtx)>::type> _guard(mtx); _once; _once = false)
    

    Allerdings bestuende dann die 'Gefahr' einer Compilerwarning.

    SCHLIMMER!

    if(a)
       synchronized(mtx)
          ++i;
    else
       ++j;
    

    bindet zu

    if(a)
       synchronized(mtx)
          ++i;
       else
          ++j;
    

    Niemals im Makros ein dangling else zulassen.

    Die dumme Warnung ist natürlich auch ein Problem.

    Wie war das nochmal? Man hat sich geeinigt, ein

    do
       tuwas
    while(false);
    

    nicht durch Warnings zu belasten, damit Makroschreiber was hinbringen können.
    Greift hier aber nicht. Also bleibts bei zwei for.



  • Kellerautomat schrieb:

    Das ist dafuer da, falls jemand break; benutzt, um rauszuspringen 😉

    💡 👍



  • volkard schrieb:

    #define retrun return
    //Den Tippfehler mache ich mehrmals täglich, das Makro spart mir 
    //Jahr Lebenszeit.
    

    Da würde ich eher gucken, ob es für den Editor nicht
    Vertipp-Korrektur-Plugins gibt, die so etwas ähnliches leisten. 🙂

    Ich finde das hier ganz nett:

    #define REQUIRES(...) ,class=typename std::enable_if<(__VA_ARGS__)>::type
    

    U.a. so zu verwenden in C++11:

    template<class T, class U
      REQUIRES( std::is_scalar<T>::value &&
                std::is_scalar<U>::value &&
                sizeof(T)==sizeot(U) )
    >
    inline T reinterpret_value(U x)
    {
      T y;
      std::memcpy(&y,&x,sizeof y);
      return y;
    }
    

    also für constrained templates. Perfekt ist es nicht. Man kann so z.b. keine
    Funktionstemplates überladen, die sich nur bei den Constraints voneinander
    unterscheiden. Aber das geht auch noch irgendwie, glaube ich ...



  • Wieso mag keiner static_assert ?



  • Typinferenz bei Rückgabetypen, die von Parametern abhängen:

    #define AUTO_RETURN(...) decltype(__VA_ARGS__) { return (__VA_ARGS__); }
    
    template <typename A, typename B>
    auto add(A a, B b) -> AUTO_RETURN( a + b )
    

    Emulation von Range Based For bei limitiertem C++11-Support (VS 2010) -- man könnte für Verschachtelung noch __LINE__ einbeziehen:

    #define FOREACH(declaration, container)																	\
    	if (bool implBroken = false) {} else																\
    	for (auto implItr = (container).begin(); implItr != (container).end() && !implBroken; ++implItr)	\
    	if (bool implPassed = false) {} else																\
    	if (implBroken = true, false) {} else																\
    	for (declaration = *implItr; !implPassed; implPassed = true, implBroken = false)
    
    std::vector<int> v = createVector();
    FOREACH(int& i, v)
    {
        i += 2;
    }
    


  • Sone schrieb:

    Wieso mag keiner static_assert ?

    Du kannst static_assert nur innerhalb der Funktion, aber nicht zur Überladungsauflösung einsetzen.



  • Nexus schrieb:

    -- man könnte für Verschachtelung noch __LINE__ einbeziehen:

    Da bin ich nicht sicher. Auf MSVC hat __LINE__ immer zu einem int-literal zur Präprozessorzeit expandiert und man konmnte supi damit neue Bezeichner bauen.

    Aber wenn ich mich recht erinnere, ging das auf GCC nicht, sondern __LINE__ wird nur zur Compilezeit zu einem int, für unsere Zwecke viel zu spät.



  • Nexus schrieb:

    Sone schrieb:

    Wieso mag keiner static_assert ?

    Du kannst static_assert nur innerhalb der Funktion, aber nicht zur Überladungsauflösung einsetzen.

    Ahh....



  • Sone schrieb:

    Nexus schrieb:

    Sone schrieb:

    Wieso mag keiner static_assert ?

    Du kannst static_assert nur innerhalb der Funktion, aber nicht zur Überladungsauflösung einsetzen.

    Ahh....

    Jepp. So gesehen, war das ein schlechtes Beispiel, weil man das auch per static_assert hätte regeln können. Aber an anderen Stellen ist das schon wichtig, dass man vor der Überladungsauflösung ein Template rauskicken kann, wenn irgendetwas nicht so passt, wie man will. Beispielsweise beim Konvertierungskonstruktor von shared_ptr. Man liest dann im Standard immer "... shall not participate in overload resultion unless ...". 🙂



  • // MSVC 2005 - spezifisch
    #define DONT_INDENT_NAMESPACE /* leer */
    
    namespace Library { DONT_INDENT_NAMESPACE
    namespace Module {
    
        void Fun();
    
    } // namespace Module
    } // namespace Library
    

    Da ich die doppelte Einrückung doof finde die MSVC 2005 hier machen würde, wenn man es "normal" schreibt.

    Sobald nach dem " { " noch etwas ausser Whitespaces oder Kommentaren kommt, rückt die Auto-Formatierung von MSVC 2005 den damit begonnenen Namespace/Scope/Block nicht mehr ein. Und das funktioniert eben auch, wenn es ein leeres Makro ist 🙂

    Bei MSVC 2012 bleibt leider nur mehr " {; " zu schreiben, oder namespace Library { namespace Module { in eine Zeile zu packen 😞



  • hustbaer schrieb:

    Bei MSVC 2012 bleibt leider nur mehr " {; " zu schreiben, oder namespace Library { namespace Module { in eine Zeile zu packen 😞

    Auch nicht

    #define DONT_INDENT_NAMESPACE ;
    

    ?



  • Swordfish schrieb:

    #define BIN_0000 0
    #define BIN_0001 1
    #define BIN_0010 2
    #define BIN_0011 3
    #define BIN_0100 4
    #define BIN_0101 5
    #define BIN_0110 6
    #define BIN_0111 7
    #define BIN_1000 8
    #define BIN_1001 9
    #define BIN_1010 a
    #define BIN_1011 b
    #define BIN_1100 c
    #define BIN_1101 d
    #define BIN_1110 e
    #define BIN_1111 f
    
    #define BIN_8_HEXIFY(b1,b2) (0x ## b1 ## b2)
    #define BIN_8_RELAY(b1,b2)  BIN_8_HEXIFY(b1,b2)
    #define BIN_8(b1,b2)        BIN_8_RELAY(BIN_ ## b1,BIN_ ## b2)
    
    #define BIN_16_HEXIFY(b1,b2,b3,b4) (0x ## b1 ## b2 ## b3 ## b4)
    #define BIN_16_RELAY(b1,b2,b3,b4)  BIN_16_HEXIFY(b1,b2,b3,b4)
    #define BIN_16(b1,b2,b3,b4)        BIN_16_RELAY(BIN_##b1,BIN_##b2,BIN_##b3,BIN_##b4)
    //...
    

    @Swordfish:
    Schlimmer gehts echt nimmer? 😉

    Dem nächsten Heinz der mir einen solchen Code abliefert darf diesen mal debuggen und ihn verifizieren. :p

    Ich sage dazu nur UAC: Ultra Albtraumhafter Code



  • volkard schrieb:

    hustbaer schrieb:

    Bei MSVC 2012 bleibt leider nur mehr " {; " zu schreiben, oder namespace Library { namespace Module { in eine Zeile zu packen 😞

    Auch nicht

    #define DONT_INDENT_NAMESPACE ;
    

    ?

    Leider auch nicht.
    Der Inhalt des #define ist ihm egal.
    Mit 2012 geht es mit dem Makro nur wenn man die "{" in die nächste Zeile setzt.

    namespace Library
    { DONT_INDENT_NAMESPACE
    namespace Module
    {
    

    Sieht finde ich komisch aus 😕
    Dann noch lieber

    namespace Library {;
    namespace Module {
    


  • Ich werf mal den Supermakro-Trick in die Runde:

    #include <iostream>
    
    namespace {
      enum color {
    #define COLOR(name) name,
    #include "colors.list"
        color_count
      };
    
      char const *const color_names[] = {
    #define COLOR(name) #name,
    #include "colors.list"
      };
    }
    
    int main() {
      std::cout << color_names[red  ] << '\n'
                << color_names[green] << '\n'
                << color_names[blue ] << '\n';
    }
    

    wobei colors.list

    COLOR(red)
    COLOR(green)
    COLOR(blue)
    
    #undef COLOR
    

    ist.



  • Hmm, nicht schlecht.



  • #define true false // happy debugging suckers


Anmelden zum Antworten