The __COUNTER__
symbol is provided by VC++ and GCC, and gives an increasing non-negative integral value each time it is used.
I\'m interested to learn w
I intend to use __COUNTER__
to give every file in our codebase a unique identifier, so that that unique code can be used in logging ASSERTs in an embedded system.
This method is much more efficient than using strings to store filenames (using __FILE__
), especially on an embedded system with tiny ROM. I thought about the idea whilst I was reading this article - Assert Yourself on Embedded.com. It's a shame that it only works with GCC-based compilers though.
It is used by Boost.Asio to implement stackless coroutines.
See this header file and examples.
Resulting coroutines look like this:
struct task : coroutine
{
...
void operator()()
{
reenter (this)
{
while (... not finished ...)
{
... do something ...
yield;
... do some more ...
yield;
}
}
}
...
};
In this blog post it is used for simulating the defer
statement of golang in C++11.
template <typename F>
struct privDefer {
F f;
privDefer(F f) : f(f) {}
~privDefer() { f(); }
};
template <typename F>
privDefer<F> defer_func(F f) {
return privDefer<F>(f);
}
#define DEFER_1(x, y) x##y
#define DEFER_2(x, y) DEFER_1(x, y)
#define DEFER_3(x) DEFER_2(x, __COUNTER__)
#define defer(code) auto DEFER_3(_defer_) = defer_func([&](){code;})
Then you can do:
int main()
{
FILE* file = open("file.txt");
defer(fclose(file));
// use the file here
// ....
}
I've used it to generate unique types in this article: http://www.codeproject.com/Articles/42021/Sealing-Classes-in-C
If I'm understanding the functionality correctly, I wished I had that functionality when I was working in Perl, adding an Event Logging function into an existing GUI. I wanted to ensure that the needed hand testing (sigh) gave us complete coverage, so I logged every test point to a file, and logging a __counter__
value made it easy to see what was missing in the coverage. As it was, I hand coded the equivalent.
A usage is in TensorFlow's REGISTER_KERNEL_BUILDER macro. Each TensorFlow Op could have one or more kernels as its implementations. These kernels are registered with a registrar. The registration of a kernel is done by defining a global variable -- the constructor of the variable can do the registration. Here the authors use __COUNTER__
to give each global variable a unique name.
#define REGISTER_KERNEL_BUILDER(kernel_builder, ...) \
REGISTER_KERNEL_BUILDER_UNIQ_HELPER(__COUNTER__, kernel_builder, __VA_ARGS__)
#define REGISTER_KERNEL_BUILDER_UNIQ_HELPER(ctr, kernel_builder, ...) \
REGISTER_KERNEL_BUILDER_UNIQ(ctr, kernel_builder, __VA_ARGS__)
#define REGISTER_KERNEL_BUILDER_UNIQ(ctr, kernel_builder, ...) \
static ::tensorflow::kernel_factory::OpKernelRegistrar \
registrar__body__##ctr##__object( \
SHOULD_REGISTER_OP_KERNEL(#__VA_ARGS__) \
? ::tensorflow::register_kernel::kernel_builder.Build() \
: nullptr, \
#__VA_ARGS__, [](::tensorflow::OpKernelConstruction* context) \
-> ::tensorflow::OpKernel* { \
return new __VA_ARGS__(context); \
});