#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.
-
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 ( ).
-
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?
-
Ach ja, übrigens:
https://github.com/Arcoth/VTMPL/blob/master/algorithms.hxxDa 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.