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 istBei MSVC 2012 bleibt leider nur mehr "
{;
" zu schreiben, odernamespace Library { namespace Module {
in eine Zeile zu packen
-
hustbaer schrieb:
Bei MSVC 2012 bleibt leider nur mehr "
{;
" zu schreiben, odernamespace Library { namespace Module {
in eine Zeile zu packenAuch 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, odernamespace Library { namespace Module {
in eine Zeile zu packenAuch 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 liebernamespace 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