coolste Makros



  • 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)
    

    Was macht der?
    edit: lol, habs.
    Sehr cooles Makro. 👍



  • Benutze ich gerne in Multithreaded Code.

    std::mutex m;
    int shared;
    
    void foo()
    {
        synchronized(m)
            ++shared;
    }
    

    Edit: Zu langsam. 🤡



  • synchronized( mutex_ ) {
       // do stuff
    }
    


  • ...



  • Sehr nützlich für 1337lerei, sprich TMP-Programmierung:

    #define split_1(str,pos)  str [ pos < sizeof str ? pos : '\0' ] 
    #define split_2(str,x)  split_1(str,x), split_1(str,x + 1) 
    #define split_4(str,x)  split_2(str,x), split_2(str,x + 2) 
    #define split_8(str,x)  split_4(str,x), split_4(str,x + 4) 
    #define split_16(str,x) split_8(str,x), split_8(str,x + 8) 
    #define split_32(str,x) split_16(str,x), split_16(str,x + 16) 
    #define split_64(str,x) split_32(str,x), split_32(str,x + 32) 
    #define split(str)    split_64(str,0)
    

    (Ist in Boost.PP AFAIK schon in anderer Form enthalten)



  • 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 ;
    

    ?


Anmelden zum Antworten