Simulating C++0x literals - with enums!
-
Sure enough a few days after ranting about the pointless complexity of User-defined literals[^] in C++0x, I have an applicaiton that could use it. for a custom numeric formatter (think "pimp my %f"), I support three explicit modes for precision: absolute, relative and scaling (similar to to %g). In application, precision usually needs to be specified individually for each value to be printed, so how do I stop myself from having tons of:
FmtX(fmtspec, value, CPrecision(2,pmRelative))
spread throughout my code? Sure enough, there's a solution, and you will probably not like it:CPrecision operator -(int precision, EPrecisionMode pm) { return CPrecision(precision, pm); }
...
FmtX(fmtspec, value, 2-pmRelative);I am not quite sure if I should be proud, or ashamed. But "Wicked code" seems about right. What do you think?
Don't attribute to stupidity what can be equally well explained by buerocracy.
My latest article | Linkify!| FoldWithUs! | sighistThis has definitely been filed in my "stupid C++ tricks" collection. Brilliant! :)
-
Sure enough a few days after ranting about the pointless complexity of User-defined literals[^] in C++0x, I have an applicaiton that could use it. for a custom numeric formatter (think "pimp my %f"), I support three explicit modes for precision: absolute, relative and scaling (similar to to %g). In application, precision usually needs to be specified individually for each value to be printed, so how do I stop myself from having tons of:
FmtX(fmtspec, value, CPrecision(2,pmRelative))
spread throughout my code? Sure enough, there's a solution, and you will probably not like it:CPrecision operator -(int precision, EPrecisionMode pm) { return CPrecision(precision, pm); }
...
FmtX(fmtspec, value, 2-pmRelative);I am not quite sure if I should be proud, or ashamed. But "Wicked code" seems about right. What do you think?
Don't attribute to stupidity what can be equally well explained by buerocracy.
My latest article | Linkify!| FoldWithUs! | sighist -
Sure enough a few days after ranting about the pointless complexity of User-defined literals[^] in C++0x, I have an applicaiton that could use it. for a custom numeric formatter (think "pimp my %f"), I support three explicit modes for precision: absolute, relative and scaling (similar to to %g). In application, precision usually needs to be specified individually for each value to be printed, so how do I stop myself from having tons of:
FmtX(fmtspec, value, CPrecision(2,pmRelative))
spread throughout my code? Sure enough, there's a solution, and you will probably not like it:CPrecision operator -(int precision, EPrecisionMode pm) { return CPrecision(precision, pm); }
...
FmtX(fmtspec, value, 2-pmRelative);I am not quite sure if I should be proud, or ashamed. But "Wicked code" seems about right. What do you think?
Don't attribute to stupidity what can be equally well explained by buerocracy.
My latest article | Linkify!| FoldWithUs! | sighistUtterly and completely hideous! :) Nearly on par with associating reading and writing data with binary bit shift operators... :omg:
¡El diablo está en mis pantalones! ¡Mire, mire! SELECT * FROM User WHERE Clue > 0 0 rows returned Save an Orange - Use the VCF! Personal 3D projects Just Say No to Web 2 Point Oh
-
Utterly and completely hideous! :) Nearly on par with associating reading and writing data with binary bit shift operators... :omg:
¡El diablo está en mis pantalones! ¡Mire, mire! SELECT * FROM User WHERE Clue > 0 0 rows returned Save an Orange - Use the VCF! Personal 3D projects Just Say No to Web 2 Point Oh
Jim Crafton wrote:
Utterly and completely hideous!Nearly on par with associating reading and writing data with binary bit shift operators...
I'm reminded of a "Why C is better than Pascal/Why Pascal is better than C" document I saw a couple decades ago. Among other things, C is better than Pascal because you can write (some small incomprehensible mass of stuff to, I think, draw a rectangle in ASCII characters). Pascal is better than C because you can't write (same mass of stuff). One of the major differences between C++ and C# is that the latter explicitly does not support the types of preprocessor "abuse" for which the former is so famous. In some ways I like those hacks; in other ways I don't. The C preprocessor can do many things, but it also has some pretty severe limitations. Once nice bit of preprocessor hacking I did awhile ago was to arrange things so if I define a macro as "X(label1) Y X(label2) Y X(label3) X(label4)" (without the quotes) the preprocessor will automatically generate enumerations NF_label1=0, FN_label2=1, FN_label2=1, etc. (consecutive numbers), along with FL_label1=1, FL_label2=2, FL_label3=4, etc. (powers of two), a structure containing some flags as well as an int for each label, and even code inside a routine for each label "tim.label1 -=n; if (tim.label1 > n) tim.flags |= FL_label1;", etc. (on the target system, performance with a loop would be unacceptable). Preprocessor abuse? Probably. But is there any better way to achieve such results without having to list the labels multiple times, and risking trouble if the different lists don't match?
-
Sure enough a few days after ranting about the pointless complexity of User-defined literals[^] in C++0x, I have an applicaiton that could use it. for a custom numeric formatter (think "pimp my %f"), I support three explicit modes for precision: absolute, relative and scaling (similar to to %g). In application, precision usually needs to be specified individually for each value to be printed, so how do I stop myself from having tons of:
FmtX(fmtspec, value, CPrecision(2,pmRelative))
spread throughout my code? Sure enough, there's a solution, and you will probably not like it:CPrecision operator -(int precision, EPrecisionMode pm) { return CPrecision(precision, pm); }
...
FmtX(fmtspec, value, 2-pmRelative);I am not quite sure if I should be proud, or ashamed. But "Wicked code" seems about right. What do you think?
Don't attribute to stupidity what can be equally well explained by buerocracy.
My latest article | Linkify!| FoldWithUs! | sighistSure is wicked hehe! :)
2+2=5 for very large amounts of 2 (always loved that one hehe!)
-
Jim Crafton wrote:
Utterly and completely hideous!Nearly on par with associating reading and writing data with binary bit shift operators...
I'm reminded of a "Why C is better than Pascal/Why Pascal is better than C" document I saw a couple decades ago. Among other things, C is better than Pascal because you can write (some small incomprehensible mass of stuff to, I think, draw a rectangle in ASCII characters). Pascal is better than C because you can't write (same mass of stuff). One of the major differences between C++ and C# is that the latter explicitly does not support the types of preprocessor "abuse" for which the former is so famous. In some ways I like those hacks; in other ways I don't. The C preprocessor can do many things, but it also has some pretty severe limitations. Once nice bit of preprocessor hacking I did awhile ago was to arrange things so if I define a macro as "X(label1) Y X(label2) Y X(label3) X(label4)" (without the quotes) the preprocessor will automatically generate enumerations NF_label1=0, FN_label2=1, FN_label2=1, etc. (consecutive numbers), along with FL_label1=1, FL_label2=2, FL_label3=4, etc. (powers of two), a structure containing some flags as well as an int for each label, and even code inside a routine for each label "tim.label1 -=n; if (tim.label1 > n) tim.flags |= FL_label1;", etc. (on the target system, performance with a loop would be unacceptable). Preprocessor abuse? Probably. But is there any better way to achieve such results without having to list the labels multiple times, and risking trouble if the different lists don't match?
supercat9 wrote:
differences between C++ and C# is that the latter explicitly does not support the types of preprocessor "abuse" for which the former is so famous
Like
goto
,#define
is one of those tools that a lot of programmers don't have sufficient experience and discretion to know when to use it, and when not to use it. Other than manifest constants and conditional compilation (which even C# supports), I've always found the key to using the preprocessor was to ask two simple questions: 1. Does using#define
make the code easier to write correctly and easier to read? Most code that abuses the preprocessor stops with the first part of the question, and misses the second part. Any time you find yourself evaluating a macro in your head in order to understand the code, the#define
is a mistake. 2. Can the macro be written effectively as 'ordinary' code? If so, then write it that way. Note the word 'effectively'. If writing the macro as ordinary code obscures the functionality too much, or increases the burden on the user too far, then maybe the macro is the better way to go. For me, the answer to Q1 must be yes, and Q2 must be no.Software Zen:
delete this;
Fold With Us![^] -
Sure enough a few days after ranting about the pointless complexity of User-defined literals[^] in C++0x, I have an applicaiton that could use it. for a custom numeric formatter (think "pimp my %f"), I support three explicit modes for precision: absolute, relative and scaling (similar to to %g). In application, precision usually needs to be specified individually for each value to be printed, so how do I stop myself from having tons of:
FmtX(fmtspec, value, CPrecision(2,pmRelative))
spread throughout my code? Sure enough, there's a solution, and you will probably not like it:CPrecision operator -(int precision, EPrecisionMode pm) { return CPrecision(precision, pm); }
...
FmtX(fmtspec, value, 2-pmRelative);I am not quite sure if I should be proud, or ashamed. But "Wicked code" seems about right. What do you think?
Don't attribute to stupidity what can be equally well explained by buerocracy.
My latest article | Linkify!| FoldWithUs! | sighistI probably would have chosen the division operator '
/
' myself. You say toe-mah-toe, I say toe-may-toe.Software Zen:
delete this;
Fold With Us![^] -
supercat9 wrote:
differences between C++ and C# is that the latter explicitly does not support the types of preprocessor "abuse" for which the former is so famous
Like
goto
,#define
is one of those tools that a lot of programmers don't have sufficient experience and discretion to know when to use it, and when not to use it. Other than manifest constants and conditional compilation (which even C# supports), I've always found the key to using the preprocessor was to ask two simple questions: 1. Does using#define
make the code easier to write correctly and easier to read? Most code that abuses the preprocessor stops with the first part of the question, and misses the second part. Any time you find yourself evaluating a macro in your head in order to understand the code, the#define
is a mistake. 2. Can the macro be written effectively as 'ordinary' code? If so, then write it that way. Note the word 'effectively'. If writing the macro as ordinary code obscures the functionality too much, or increases the burden on the user too far, then maybe the macro is the better way to go. For me, the answer to Q1 must be yes, and Q2 must be no.Software Zen:
delete this;
Fold With Us![^]Gary R. Wheeler wrote:
1. Does using #define make the code easier to write correctly and easier to read?
I'd include 'modify' as an important criterion. In some cases, certain uses of macros can make code easy to write, and easy to modify, even if it's difficult to read. For example, which of the following styles (typed from memory) seems easier to read:
/* ub == unsigned byte; ui = unsigned 16-bit integer; ul = unsigned 32-bit integer */
struct {
ub format;
ub this;
ui that;
ul whatever;
...
} MY_THING;const MY_THING default_my_thing = {5,2,5,199, ...};
Putting the default values of all the parameters in a list after the end of the definition, or...
/* Structure definition must be on one "line"...
(extend the line with backslashes). X must appear after every item but the last. */
#define MAKE_MY_THING \
ITEM(ub format, 5) X\
ITEM(ub this, 2) X\
ITEM(ui that, 5) X\
ITEM(ul whatever, 199) X\
...The MAKE_MY_THING macro can then be invoked twice--once to define the structure, and once to create the default instance (the definitions of ITEM and X will change between the invocations). I wouldn't consider that code to be particularly easy to decipher, but when I switched from the former style to the latter style, I stopped having problems with mis-aligned parameters. The biggest annoyance is that if the initializer for a structure item commas, it must be defined in a separate macro. I would regard that code as easier to write and modify than the "normal" method; harder to decipher, but IMHO worth the trouble. BTW, in this particular application constant storage was separate from variable storage, so having the variable be non-const and initializing it at run-time would not have been a good option.
-
I probably would have chosen the division operator '
/
' myself. You say toe-mah-toe, I say toe-may-toe.Software Zen:
delete this;
Fold With Us![^]I've picked '-' for it's proximity to the hyphen (and we germans are known to hyphenate a lot..)
Don't attribute to stupidity what can be equally well explained by buerocracy.
My latest article | Linkify!| FoldWithUs! | sighist -
Jim Crafton wrote:
Utterly and completely hideous!Nearly on par with associating reading and writing data with binary bit shift operators...
I'm reminded of a "Why C is better than Pascal/Why Pascal is better than C" document I saw a couple decades ago. Among other things, C is better than Pascal because you can write (some small incomprehensible mass of stuff to, I think, draw a rectangle in ASCII characters). Pascal is better than C because you can't write (same mass of stuff). One of the major differences between C++ and C# is that the latter explicitly does not support the types of preprocessor "abuse" for which the former is so famous. In some ways I like those hacks; in other ways I don't. The C preprocessor can do many things, but it also has some pretty severe limitations. Once nice bit of preprocessor hacking I did awhile ago was to arrange things so if I define a macro as "X(label1) Y X(label2) Y X(label3) X(label4)" (without the quotes) the preprocessor will automatically generate enumerations NF_label1=0, FN_label2=1, FN_label2=1, etc. (consecutive numbers), along with FL_label1=1, FL_label2=2, FL_label3=4, etc. (powers of two), a structure containing some flags as well as an int for each label, and even code inside a routine for each label "tim.label1 -=n; if (tim.label1 > n) tim.flags |= FL_label1;", etc. (on the target system, performance with a loop would be unacceptable). Preprocessor abuse? Probably. But is there any better way to achieve such results without having to list the labels multiple times, and risking trouble if the different lists don't match?
There's really nothing keeping you from using the C preprocessor with C#, VB, or any language; it's just a text processor.
-
supercat9 wrote:
differences between C++ and C# is that the latter explicitly does not support the types of preprocessor "abuse" for which the former is so famous
Like
goto
,#define
is one of those tools that a lot of programmers don't have sufficient experience and discretion to know when to use it, and when not to use it. Other than manifest constants and conditional compilation (which even C# supports), I've always found the key to using the preprocessor was to ask two simple questions: 1. Does using#define
make the code easier to write correctly and easier to read? Most code that abuses the preprocessor stops with the first part of the question, and misses the second part. Any time you find yourself evaluating a macro in your head in order to understand the code, the#define
is a mistake. 2. Can the macro be written effectively as 'ordinary' code? If so, then write it that way. Note the word 'effectively'. If writing the macro as ordinary code obscures the functionality too much, or increases the burden on the user too far, then maybe the macro is the better way to go. For me, the answer to Q1 must be yes, and Q2 must be no.Software Zen:
delete this;
Fold With Us![^]A few months ago I was working playing with some code (C#) that I wanted to be very fast. There was a sequence of statements that I needed in two places. I didn't want to have to maintain two copies and I didn't want the overhead of a method (and wasn't sure it would be inlined), so I wrote a macro and used the C preprocessor.
-
A few months ago I was working playing with some code (C#) that I wanted to be very fast. There was a sequence of statements that I needed in two places. I didn't want to have to maintain two copies and I didn't want the overhead of a method (and wasn't sure it would be inlined), so I wrote a macro and used the C preprocessor.
PIEBALDconsult wrote:
(C#)...so I wrote a macro and used the C preprocessor.
I thought C# didn't allow anything "fun" within a macro. Or did you invoke the preprocessor separately? One thing I've sometimes been pondering is whether it would be worthwhile to write a preprocessor that would pull out string literals and do magical mystical things with them; I do a lot of embedded systems work, and some projects would benefit from: -1- Mapping strings to different character sets, since not everything in the world uses ASCII. -2- Packing or compressing strings via various methods, so as to save code space. -3- Pulling strings out of the code and storing them in a separate file. Generally I've handled all string munging in a process separate from my code builds. On the other hand, I've sometimes wondered whether it would make sense to write my own preprocessor to sit between the C preprocessor and the compiler. BTW, another item I'd add to the list, if I could figure out how to actually make it work, would be to convert "printf"-style calls to the most efficient form for the microcontrollers I use. On something like the PIC-18 series, all variables, including automatic ones, are allocated at fixed addresses. Further, a called function can manipulate the call/return stack. Thus, something like:
; printf("Hello %04d %08lX %02X",intvar,longvar,bytevar & 0x7F);
movlw <msg
movwf ?printf_ptr
movlw >msg
movwf ?printf_ptr+1
movf _intvar,w
movwf ?varparam
movf >_intvar+1,w
movwf ?varparam+1
movf _longvar,w
movwf ?varparam+2
movf _longvar+1,w
movwf ?varparam+3
movf _longvar+2,w
movwf ?varparam+4
movf _longvar+3,w
movwf ?varparam+5
movf _bytevar,w
andlw 0x7F
movwf ?varparam+6
clrf ?varparam+7
call _printf ; High byte of last parameter</pre>
...
msg "Hello %04d %08lX %02X",0which is 22 instructions plus 30 bytes of data (74 bytes total) could become something like:
; printf("Hello %04d %08lX %02X",intvar,longvar,bytevar & 0x7F);
movf _bytevar,w ; The only variable in a non-trivial expression
andlw 0x7F
movwf ?varparam
call _doformat
byte "Hello "
byte 0x81,0x44,>_intvar,<_intvar
byte " "
byte 0x82,0xC8,>_longvar,<_longvarvar
byte " "
byte 0x84,0xC2 ; Use byte from varparam
byte 0,0 ; Second zero needed if odd number of bytes
; Next in -
A few months ago I was working playing with some code (C#) that I wanted to be very fast. There was a sequence of statements that I needed in two places. I didn't want to have to maintain two copies and I didn't want the overhead of a method (and wasn't sure it would be inlined), so I wrote a macro and used the C preprocessor.
:omg:
Software Zen:
delete this;
Fold With Us![^] -
:omg:
Software Zen:
delete this;
Fold With Us![^]how to hack in my system
-
how to hack in my system
-
Sure enough a few days after ranting about the pointless complexity of User-defined literals[^] in C++0x, I have an applicaiton that could use it. for a custom numeric formatter (think "pimp my %f"), I support three explicit modes for precision: absolute, relative and scaling (similar to to %g). In application, precision usually needs to be specified individually for each value to be printed, so how do I stop myself from having tons of:
FmtX(fmtspec, value, CPrecision(2,pmRelative))
spread throughout my code? Sure enough, there's a solution, and you will probably not like it:CPrecision operator -(int precision, EPrecisionMode pm) { return CPrecision(precision, pm); }
...
FmtX(fmtspec, value, 2-pmRelative);I am not quite sure if I should be proud, or ashamed. But "Wicked code" seems about right. What do you think?
Don't attribute to stupidity what can be equally well explained by buerocracy.
My latest article | Linkify!| FoldWithUs! | sighist