Reputation: 3565
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?
Upvotes: 71
Views: 67505
Reputation: 112404
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)
Upvotes: 12
Reputation: 3644
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.
Upvotes: 0
Reputation: 394
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")
Upvotes: 0
Reputation: 58627
__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.
Upvotes: 3
Reputation: 1012
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.
Upvotes: 0
Reputation: 73
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
Upvotes: 5
Reputation: 5836
__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
Upvotes: 0
Reputation: 3951
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
// ....
}
Upvotes: 2
Reputation: 651
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
Upvotes: 2
Reputation: 22094
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.
Upvotes: 0
Reputation:
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;
}
}
}
...
};
Upvotes: 3
Reputation: 3276
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; }
}
Upvotes: 1
Reputation: 701
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); \
});
Upvotes: 3
Reputation: 1297
It's used in the xCover code coverage library, to mark the lines that execution passes through, to find ones that are not covered.
Upvotes: 13
Reputation: 137900
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.
Upvotes: 12
Reputation: 8961
__COUNTER__
is guaranteed to be unique unlike __LINE__
. Some compilers allow __LINE__
to be reset. #include files will also reset __LINE__
.
Upvotes: 0
Reputation: 3328
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.
Upvotes: -2
Reputation:
__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.
Upvotes: 68
Reputation: 13767
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.
Upvotes: 3
Reputation: 340366
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.
Upvotes: 14