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 whether anyone's ever used it, and whether it's something that would be worth standardising?
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 whether anyone's ever used it, and whether it's something that would be worth standardising?
It's used in the xCover code coverage library, to mark the lines that execution passes through, to find ones that are not covered.
__COUNTER__
is useful anywhere you need a unique name. I have used it extensively for RAII style locks and stacks. Consider:
struct TLock
{
void Lock();
void Unlock();
}
g_Lock1, g_Lock2;
struct TLockUse
{
TLockUse( TLock &lock ):m_Lock(lock){ m_Lock.Lock(); }
~TLockUse(){ m_Lock.Unlock(); }
TLock &m_Lock;
};
void DoSomething()
{
TLockUse lock_use1( g_Lock1 );
TLockUse lock_use2( g_Lock2 );
// ...
}
It gets tedious to name the lock uses, and can even become a source of errors if they're not all declared at the top of a block. How do you know if you're on lock_use4
or lock_use11
? It's also needless pollution of the namespace - I never need to refer to the lock use objects by name. So I use __COUNTER__
:
#define CONCAT_IMPL( x, y ) x##y
#define MACRO_CONCAT( x, y ) CONCAT_IMPL( x, y )
#define USE_LOCK( lock ) TLockUse MACRO_CONCAT( LockUse, __COUNTER__ )( lock )
void DoSomething2()
{
USE_LOCK( g_Lock1 );
USE_LOCK( g_Lock2 );
// ...
}
But don't get hung up on the fact I called the objects locks - any function(s) that need to get called in matching pairs fit this pattern. You might even have multiple uses on the same "lock" in a given block.
use_lock(g_Lock1, g_Lock2)
function that is smart enough to order the locks to avoid deadlocking. –
Darkling LockUse##__COUNTER__
? –
Funky I've used it in a compile-time assertion macro to have the macro create a name for a typedef that will be unique. See
if you want the gory details.
__COUNTER__
is not available, the failover is to use __LINE__
, but that will fail of you have the bad luck of using the macro on the same line in two different source files. –
Ademption __COUNTER__
will change each time you use it. A unique name that you cannot mention again has limited uses. –
Antarctic I've never used it for anything but a DEBUG macro. It's convenient to be able to say
#define WAYPOINT \
do { if(dbg) printf("At marker: %d\n", __COUNTER__); } while(0);
WAYPOINT();
Also, the "silent" semicolon produces warnings that irritate devs. –
Darkling if (foo) WAYPOINT; else bar();
. You're re-introducing the problem that do { foo } while (0)
solves :) –
Jocasta do { foo } while (0)
in macros is to avoid that problem with if
/else
statements. If you're not worried about if statements without braces (which is fair enough), why not remove the whole while (0)
wrapper? Either way, the while (0)
wrapper is rendered totally pointless with that trailing semicolon. –
Profuse fprintf(stderr, "Checkpoint 1\n");
and rely on an editor macro to adjust the number whenever I paste it into the code. That way I can clearly make the connection by looking at the code and its output. –
Misstate __FILE__
and __LINE__
to output the precise location, the use of __COUNTER__
to make the messages distinguishable is pretty mute... –
Misstate It's used in the xCover code coverage library, to mark the lines that execution passes through, to find ones that are not covered.
I'm interested to learn whether anyone's ever used it,
Yes, but as you can see from many examples in this Q&A, __LINE__
, which is standardized, would also be sufficient in most cases.
__COUNTER__
is only really necessary in cases where the count must increase by one each time, or it must have continuity over several #include
files.
and whether it's something that would be worth standardising?
__COUNTER__
, unlike __LINE__
, is very dangerous because it depends on which header files are included and what order. If two .cpp
files (translation units) include a header file that use __COUNTER__
, but the header file obtains different count sequences in the different instances, they may use different definitions of the same thing and violate the one-definition rule.
One-definition rule violations are very difficult to catch and potentially create bugs and security risks. The few use-cases of __COUNTER__
don't really outweigh the downside and lack of scalability.
Even if you never ship code that uses __COUNTER__
, it can be useful when prototyping an enumeration sequence, saving you the trouble of assigning names before the membership is concrete.
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.
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;
}
}
}
...
};
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); \
});
I've used __COUNTER__
to automatically generate type IDs for Entities & Colliders in an object-oriented game.
This game uses polymorphism to achieve its functionality. To serialize child objects, I had to figure out a way to store Entity child types & serialize/deserialize them for scene saving & loading. When reading an entity from a save file (deserializing), I needed to know what properties to expect to read; with __COUNTER__
, I have a unique and constant ID for each entity class and can load them in as the proper entity type using this ID.
This approach means that to make a new Entity type serializable, all I have to add is typeID = __COUNTER__;
within the constructor to overwrite the default ID. In the case of Sprite:
Sprite(/* TODO: Sprite Arguments */) : Entity(/* TODO: Entity Arguments */) {
typeID = __COUNTER__;
}
... and go on to outline its iostream overloads:
friend std::ostream& operator<<(std::ostream& os, const Sprite& rhs) {
return os << /* TODO: Outline Output */;
}
friend std::istream& operator>>(std::istream& is, Sprite& rhs) {
return is >> /* TODO: Outline Input */;
}
It's a very lightweight approach to generating type IDs for your classes, and avoids a bunch of complicated logic. As a preprocessor command it's pretty basic, but it provides a useful tool for some key appliances.
Note: If you want to restart the ID value to 0 when calling the counter, store its value on the generation of your first ID and subtract all subsequent IDs by that value.
Thanks for reading! -YZM
I've used it for a driver shim layer, where I needed to make sure at least one physical driver was enabled.
For example:
#if defined( USE_DRIVER1 )
#include "driver1.h"
int xxx1 = __COUNTER__;
#endif
#if defined( USE_DRIVER2 )
#include "driver2.h"
int xxx2 = __COUNTER__;
#endif
#if __COUNTER__ < 1
#error Must enable at least one driver.
#endif
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
// ....
}
std::unique_ptr
solve that problem using a custom deleter. –
August It's used in ClickHouse's metrics system.
namespace CurrentMetrics
{
#define M(NAME) extern const Metric NAME = __COUNTER__;
APPLY_FOR_METRICS(M)
#undef M
constexpr Metric END = __COUNTER__;
std::atomic<Value> values[END] {}; /// Global variable, initialized by zeros.
const char * getDescription(Metric event)
{
static const char * descriptions[] =
{
#define M(NAME) #NAME,
APPLY_FOR_METRICS(M)
#undef M
};
return descriptions[event];
}
Metric end() { return END; }
}
I have found it useful for displaying steps in a UI. This makes it really easy to add, remove, or reorder steps without worrying about the steps getting mislabeled.
#include <iostream>
#define STR_IMPL(s) #s
#define STR(s) STR_IMPL(s)
#define STEP STR(__COUNTER__) ": "
int main()
{
std::cout
<< STEP "foo\n"
<< STEP "bar\n"
<< STEP "qux\n"
;
}
Output:
0: foo
1: bar
2: qux
Having it start from 1 instead of 0 is left as an exercise.
__COUNTER__
can be used to establish unique local variables. The problem with __COUNTER__
is that its value is different on each expansion. But what we can do is split our macro into two:
#define MACRO_IMPL(COUNTER, ARG1, ARG2, ..., ARGN)
#define MACRO(ARG1, ARG2, ..., ARGN) MACRO_IMPL(__COUNTER__, ARG1, ARG2, ... ARGN)
So now MACRO_IMPL
has a unique counter, via the COUNTER
argument value, which it can use to generate local symbols that are defined and referenced multiple times. E.g.
#define CAT(A, B) A ## B
#define XCAT(A, B) CAT(A, B)
#define U(COUNTER) XCAT(__U, COUNTER)
#define REPEAT_IMPL(C, N) for (int U(C) = 0; U(C) < (N); U(C)++)
#define REPEAT(N) REPEAT_IMPL(__COUNTER__, N)
REPEAT (42) { puts("Hey!"); REPEAT (73) { puts("Cool!"); } }
Expansion by gcc -E -
:
# 1 "<stdin>"
# 1 "<built-in>"
# 1 "<command-line>"
# 31 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 32 "<command-line>" 2
# 1 "<stdin>"
# 9 "<stdin>"
for (int __U0 = 0; __U0 < (42); __U0++) { puts("Hey!"); for (int __U1 = 0; __U1 < (73); __U1++) { puts("Cool!"); } }
I put the loops in one line on purpose; that's a situation where using __LINE__
instead of __COUNTER__
could break.
__COUNTER__
is guaranteed to be unique unlike __LINE__
. Some compilers allow __LINE__
to be reset. #include files will also reset __LINE__
.
__LINE__
. –
Francois __LINE__
is useful in that it is not unique when a particular macro is being expanded: all occurrences of __LINE__
are the same, which lets you do useful things like #define loop(...) ... for (__uniq(i) = 0; __uniq(i) < N; __uniq(i)++)
where __uniq
uses __LINE__
to generate an identifier like __i_42
. All occurrences of this will share the line number wheree the macro call occurs. –
Antarctic In our code we forgot to add testcases for some of our products. I implemented now some macros so we can assert at compile time that we have testcases for each product that we are adding or removing.
__COUNTER__
is very useful when you are encrypting strings in runtime and you want every string to have a unique key, without storing a counter somewhere for the key of your encryption you can use Counter to be sure that every string has it's own unique key!.
I use it in my XorString
1 header library which decrypts strings in run-time, so if any hackers/crackers try to look at my binary file they won't find the strings there, but when the program runs every string is decrypted and shown as normal.
#pragma once
#include <string>
#include <array>
#include <cstdarg>
#define BEGIN_NAMESPACE( x ) namespace x {
#define END_NAMESPACE }
BEGIN_NAMESPACE(XorCompileTime)
constexpr auto time = __TIME__;
constexpr auto seed = static_cast< int >(time[7]) + static_cast< int >(time[6]) * 10 + static_cast< int >(time[4]) * 60 + static_cast< int >(time[3]) * 600 + static_cast< int >(time[1]) * 3600 + static_cast< int >(time[0]) * 36000;
// 1988, Stephen Park and Keith Miller
// "Random Number Generators: Good Ones Are Hard To Find", considered as "minimal standard"
// Park-Miller 31 bit pseudo-random number generator, implemented with G. Carta's optimisation:
// with 32-bit math and without division
template < int N >
struct RandomGenerator
{
private:
static constexpr unsigned a = 16807; // 7^5
static constexpr unsigned m = 2147483647; // 2^31 - 1
static constexpr unsigned s = RandomGenerator< N - 1 >::value;
static constexpr unsigned lo = a * (s & 0xFFFF); // Multiply lower 16 bits by 16807
static constexpr unsigned hi = a * (s >> 16); // Multiply higher 16 bits by 16807
static constexpr unsigned lo2 = lo + ((hi & 0x7FFF) << 16); // Combine lower 15 bits of hi with lo's upper bits
static constexpr unsigned hi2 = hi >> 15; // Discard lower 15 bits of hi
static constexpr unsigned lo3 = lo2 + hi;
public:
static constexpr unsigned max = m;
static constexpr unsigned value = lo3 > m ? lo3 - m : lo3;
};
template <>
struct RandomGenerator< 0 >
{
static constexpr unsigned value = seed;
};
template < int N, int M >
struct RandomInt
{
static constexpr auto value = RandomGenerator< N + 1 >::value % M;
};
template < int N >
struct RandomChar
{
static const char value = static_cast< char >(1 + RandomInt< N, 0x7F - 1 >::value);
};
template < size_t N, int K, typename Char >
struct XorString
{
private:
const char _key;
std::array< Char, N + 1 > _encrypted;
constexpr Char enc(Char c) const
{
return c ^ _key;
}
Char dec(Char c) const
{
return c ^ _key;
}
public:
template < size_t... Is >
constexpr __forceinline XorString(const Char* str, std::index_sequence< Is... >) : _key(RandomChar< K >::value), _encrypted{ enc(str[Is])... }
{
}
__forceinline decltype(auto) decrypt(void)
{
for (size_t i = 0; i < N; ++i) {
_encrypted[i] = dec(_encrypted[i]);
}
_encrypted[N] = '\0';
return _encrypted.data();
}
};
//--------------------------------------------------------------------------------
//-- Note: XorStr will __NOT__ work directly with functions like printf.
// To work with them you need a wrapper function that takes a const char*
// as parameter and passes it to printf and alike.
//
// The Microsoft Compiler/Linker is not working correctly with variadic
// templates!
//
// Use the functions below or use std::cout (and similar)!
//--------------------------------------------------------------------------------
static auto w_printf = [](const char* fmt, ...) {
va_list args;
va_start(args, fmt);
vprintf_s(fmt, args);
va_end(args);
};
static auto w_printf_s = [](const char* fmt, ...) {
va_list args;
va_start(args, fmt);
vprintf_s(fmt, args);
va_end(args);
};
static auto w_sprintf = [](char* buf, const char* fmt, ...) {
va_list args;
va_start(args, fmt);
vsprintf(buf, fmt, args);
va_end(args);
};
static auto w_sprintf_ret = [](char* buf, const char* fmt, ...) {
int ret;
va_list args;
va_start(args, fmt);
ret = vsprintf(buf, fmt, args);
va_end(args);
return ret;
};
static auto w_sprintf_s = [](char* buf, size_t buf_size, const char* fmt, ...) {
va_list args;
va_start(args, fmt);
vsprintf_s(buf, buf_size, fmt, args);
va_end(args);
};
static auto w_sprintf_s_ret = [](char* buf, size_t buf_size, const char* fmt, ...) {
int ret;
va_list args;
va_start(args, fmt);
ret = vsprintf_s(buf, buf_size, fmt, args);
va_end(args);
return ret;
};
//Old functions before I found out about wrapper functions.
//#define XorStr( s ) ( XorCompileTime::XorString< sizeof(s)/sizeof(char) - 1, __COUNTER__, char >( s, std::make_index_sequence< sizeof(s)/sizeof(char) - 1>() ).decrypt() )
//#define XorStrW( s ) ( XorCompileTime::XorString< sizeof(s)/sizeof(wchar_t) - 1, __COUNTER__, wchar_t >( s, std::make_index_sequence< sizeof(s)/sizeof(wchar_t) - 1>() ).decrypt() )
//Wrapper functions to work in all functions below
#define XorStr( s ) []{ constexpr XorCompileTime::XorString< sizeof(s)/sizeof(char) - 1, __COUNTER__, char > expr( s, std::make_index_sequence< sizeof(s)/sizeof(char) - 1>() ); return expr; }().decrypt()
#define XorStrW( s ) []{ constexpr XorCompileTime::XorString< sizeof(s)/sizeof(wchar_t) - 1, __COUNTER__, wchar_t > expr( s, std::make_index_sequence< sizeof(s)/sizeof(wchar_t) - 1>() ); return expr; }().decrypt()
END_NAMESPACE
While this is an old post, I recently find that __COUNTER__
can effectively generate a C++ namedtuple
easily, converting your struct into a tuple.
This allows me to implement type reflection like boost::hana
, but way more faster.
I post the POC here with several use cases and benchmarks. https://github.com/johnjohnlin/namedtuple
struct S { int x; float y; string z; };
// DEFINE_NAMEDTUPLE(S2)
struct S2 {
static constexpr int Base = 100 + 1; // __COUNTER__ is 100 here
// NT_MEMBER
int x;
int& get(integral_constant<unsigned, 101-Base>) { return x; }
// NT_MEMBER
float y;
float& get(integral_constant<unsigned, 102-Base>) { return y; }
// NT_MEMBER
string z;
string& get(integral_constant<unsigned, 103-Base>) { return z; }
// END_DEFINE_NAMEDTUPLE(S2)
static constexpr int End = 104;
static constexpr int num_members = End - Base;
template<unsigned x> auto& get() { return get(integral_constant<unsigned, x>()); }
};
S2 s_namedtuple;
s_namedtuple.get<1>(); // float, the reference of y
static_assert(sizeof(S2) == sizeof(S)); // namedtuple does not add extra members!
static_assert(sizeof(S2::num_members) == 3u); // namedtuple also provides ::num_members
S2::get_name<1>(); // string("y")
It's also very useful to overcome some of the limitations of C++ enums. Consider e.g. a hierarchy of widgets, each with its own set of specific events, which all must have different IDs (e.g. for using them as keys in a callback map):
template <int N> struct EnumValue { static constexpr int value = N; };
#define UNIQUE_ID EnumValue<__COUNTER__>::value
class Widget {
public:
enum Event {
A = UNIQUE_ID,
B = UNIQUE_ID
};
};
class Button : public Widget {
public:
enum Event {
C = UNIQUE_ID
};
};
#include <iostream>
int main()
{
std::cout << (int) Widget::Event::A << ", " << (int) Button::Event::C << "\n";
}
While there are other techniques to achieve (roughly) the same, most of them are more cumbersome/tedious.
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.
__COUNTER__
gets reset for each cpp file though, so headers would get a different number depending on the order they're included. I think you're misremembering. –
Darkling © 2022 - 2024 — McMap. All rights reserved.