3 ms·
Instead of the tricks with __COUNTER__ it is better to define the macro such that it also defines initializer function which registers whatever you want to regi
by dfox 9y ago
Instead of the tricks with __COUNTER__ it is better to define the macro such that it also defines initializer function which registers whatever you want to register dynamically on program startup. The way of doing that is somewhat non-portable but essentially every interesting compiler-platform combination has straightforward way to do that as it is needed for both C++ (to call constructors of global variables) and ObjectiveC (as part of the code that @implementation expands into) implementations.
Edit: also, syntax-wise it seems to me that it is better do define the macro such that it can be used as
define_foo(blabla...){ ... code ...}
In this case this would involve code like
#define define_foo(name, ...) \
static foo_ ## name(); \
... initializer function ...
static foo_ ## name()
which also solves the first problem mentioned in the article.
- Gibbon1 9y agoI suppose you could do a linked list hack of sorts to. Just create a linked list of goto labels. When done iterate through to clean up everything. Personal wish for an extension to c is to be able to create a list function arguments and slop that around until needed. int BarBaz(int bar, int baz) { return bar+baz; } auto foo = args_of(BarBaz(10, 20)); ... ... printf( "BarBaz = %i\n", BarBaz(foo)};
- mort96 9y agoI agree with your point about syntax; it would have been nice if the syntax was `define(blah) { ... }` and `it("whatever") { ... }`. However, I don't think that's possible, because I need to include code after the end of the block. That might not be obvious from the simplified macros I used in my example, but it's pretty clear by looking at the actual definitions. The describe and subdesc-macros (https://github.com/mortie/snow/blob/a9ad850df456f78bcf96e1aaeb5f42081f243f63/snow/snow.h#L377 https://github.com/mortie/snow/blob/a9ad850df456f78bcf96e1aa...) need to increment counters and print their status after the block, and the `it` macro (https://github.com/mortie/snow/blob/a9ad850df456f78bcf96e1aaeb5f42081f243f63/snow/snow.h#L336 https://github.com/mortie/snow/blob/a9ad850df456f78bcf96e1aa...) needs to run deferred expressions. I think it would be possible to implement the `describe` macro such that it can be used as `describe(blah) { ... }`, because that defines a function and we can both give the function argument and expect return values from it, but I can't think of any way to do it with the other macros which just create regular `do { ... } while(0)` blocks. If I'm wrong, please show me how; the `foo(blah) { ... }` syntax would make the __LINE__ macro work, it would play better with auto indenters and syntax highlighters, and it would give prettier error messages if you have a syntax error in a test case. I just can't see any way it would be possible.
- fanf2 9y ago#include <stdio.h> #define before_after(before, after) \ for(int before_after_##__LINE__ = 0; \ before_after_##__LINE__ < 3; \ before_after_##__LINE__++) \ if(before_after_##__LINE__ == 0) { \ printf("%s\n", before); \ } else if(before_after_##__LINE__ == 2) { \ printf("%s\n", after); \ } else int main(void) { before_after("hello", "world") { printf("to all the\n"); } return(0); }
- kreco 9y agoYou should combine "__COUNTER___" with "before_after_##__LINE__" to make a unique identifier more robust. Your snippet won't work with this inline example: before_after("hello", "world") { before_after("hello", "world") { }}