65

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?

ThinkingStiff
  • 64,767
  • 30
  • 146
  • 239
dcw
  • 3,481
  • 2
  • 22
  • 30
  • 9
    Curious: is __COUNTER__ defined in the C99 standard? (Or maybe the C++ standard?) – strager Mar 17 '09 at 03:59
  • 2
    I don't think it's defined in either. AFAIK, it's an extension that started in VC++, and went over to GCC recently. Don't know if any other compilers support. Maybe if there's a reallu important use for it there'd be reason to standardize ... – dcw Mar 17 '09 at 05:48
  • 2
    I've used it, but it was so long ago that I can't remember why. – Mark Ransom Aug 18 '09 at 17:31
  • 3
    @dcw: clang supports it. – Keith Thompson Dec 23 '14 at 00:03

20 Answers20

62

__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.

  • 8
    It's a significantly better idea to use a single `use_lock(g_Lock1, g_Lock2)` function that is smart enough to order the locks to avoid deadlocking. – Mooing Duck Feb 17 '15 at 01:46
  • 8
    Why are MACRO_CONCAT and CONCAT_IMPL needed? Can't we directly write `LockUse##__COUNTER__`? – Cœur Feb 20 '16 at 07:37
  • 11
    @Cœur - FYI, I asked that same question a couple of years ago on this site: [*Why is a level of indirection needed for this concatenation macro?*](http://stackoverflow.com/questions/19666142/why-is-a-level-of-indirection-needed-for-this-concatenation-macro) – DaoWen Jun 09 '16 at 16:58
14

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.

Community
  • 1
  • 1
Michael Burr
  • 333,147
  • 50
  • 533
  • 760
  • Why do you want unique name for each of typedefs? They will be either defined eqiuvalently or compilation will fail. – n0rd Mar 17 '09 at 14:09
  • @nOrd - hmm - either it's over-engineered or there's a reason that's escaping me... but, I probably won't revisit it, since the C_ASSERT stuff seems to be working just fine for me. – Michael Burr May 10 '09 at 01:23
  • 3
    Equivalent definitions are an error at least in C89, I believe. I think C99 and C++11 both allow redundant typedefs, but they weren't always permitted. – Jeff Walden Jul 03 '13 at 22:38
  • If you invoke the macro more than once, you need each typedef to be unique. If `__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. – EBlake Apr 11 '16 at 17:55
  • How do you refer to that typedef again? `__COUNTER__` will change each time you use it. A unique name that you cannot mention again has limited uses. – Kaz Apr 07 '22 at 21:33
13

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);
Charlie Martin
  • 110,348
  • 25
  • 193
  • 263
  • 9
    Interesting. But how is this as good as / better than using __FILE__. After all, that will tell you exactly where the waypoint is, rather than perhaps having to search the file for WAYPOINT instances? Am I missing something ;-) – dcw Mar 17 '09 at 02:21
  • 2
    Well, you might be missing me saying "this is *all* I've ever found it useful for." Which isn't very. – Charlie Martin Mar 17 '09 at 02:25
  • Ok. Thanks for clarifying. btw, you might want to look at the code. Not sure the format specifier type is what you intended. ;-) – dcw Mar 17 '09 at 02:44
  • 3
    Me again: kudos on the do {} while(0), btw. :-) – dcw Mar 17 '09 at 02:45
  • What, %d? It was always %d. Nothing else. Never changed. Yeah, that's the ticket. – Charlie Martin Mar 17 '09 at 03:26
  • I think using && may be more useful than the do/if. That reduces readability, though... – strager Mar 17 '09 at 03:56
  • strager, what benefit do you see in using &&? And can you construct a case where WAYPOINT could appear that would give unexpected results using && instead? – Charlie Martin Mar 17 '09 at 04:01
  • @Martin, Using && allows the 'function' to be used as a normal function with a return value (in most cases). You can for example do: if(WAYPOINT) { more debug }. Macro would be: #define WAYPOINT (dbg && (printf("..", __COUNTER_) >= 0)) – strager Mar 17 '09 at 04:04
  • 1
    Right. Now think about this inside an if. See, eg, here: http://mail.nl.linux.org/kernelnewbies/2001-09/msg00230.html There's a reason this is the canonical way of doing a complex #define – Charlie Martin Mar 17 '09 at 04:12
  • @Martin, I'm not convinced do/white is as effective as && in this case. Whatever, though. I'll stop my arguing. – strager Mar 17 '09 at 04:14
  • 5
    No there isn't. It's there on purpose. If someone writes WAYPOINT; the extra ; is a no-op, silently optimized out. Do it the other way and it can become a syntax error somewhere south of the macro, with the cause hidden in the macro body. – Charlie Martin Mar 17 '09 at 14:06
  • 1
    @CharlieMartin: Put parenthesis after the name and developers stop making that mistake: `WAYPOINT();` Also, the "silent" semicolon produces warnings that irritate devs. – Mooing Duck Feb 17 '15 at 01:48
  • Re the two ;'s -- not on any compiler I've got access to. – Charlie Martin Feb 17 '15 at 02:10
  • 16
    The second semicolon will make it fail for something like `if (foo) WAYPOINT; else bar();`. You're re-introducing the problem that `do { foo } while (0)` solves :) – domen Aug 15 '16 at 09:39
  • "Doctor, it hurts when I do *this*." "Well, don't *do* that!" -- Braces are your friend. – Charlie Martin Aug 15 '16 at 16:47
  • 10
    @CharlieMartin The whole point of `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. – Arthur Tacca May 15 '17 at 16:10
  • @ArthurTacca You can't know where your macro will be used in the future, so you can't know you're not worried about braceless ifs. – Charlie Martin May 15 '17 at 18:13
  • 4
    In that case you DO need to remove the trailing semicolon! That's what I meant by "either way ...". – Arthur Tacca May 15 '17 at 20:27
  • 1
    So, you get unique waypoint messages. That's fine. But how do you *find* the line of code that actually produced that message?!? I'd much rather insert an `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. – cmaster - reinstate monica Apr 25 '20 at 09:17
  • @cmaster try __FILE__ and __LINE__ – Charlie Martin Apr 25 '20 at 15:15
  • @CharlieMartin If you use `__FILE__` and `__LINE__` to output the precise location, the use of `__COUNTER__` to make the messages distinguishable is pretty mute... – cmaster - reinstate monica Apr 25 '20 at 19:27
  • You mean "moot" and so what? I answered the question. – Charlie Martin Apr 26 '20 at 00:01
13

It's used in the xCover code coverage library, to mark the lines that execution passes through, to find ones that are not covered.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
JamieH
  • 1,257
  • 3
  • 12
  • 19
12

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.

Potatoswatter
  • 134,909
  • 25
  • 265
  • 421
3

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;
       }
     }
   }
   ...
};
3

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);          \
            });
cxwangyi
  • 653
  • 1
  • 8
  • 15
3

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.

Leonard
  • 13,269
  • 9
  • 45
  • 72
  • 1
    As I reread my own post, I didn't really hand-code the equivalent. I just put counters in by hand. (hard coded all the numbers throughout each file.) That's why I wish I'd had the functionality. – Leonard May 11 '09 at 01:11
3

Generating Class Type IDs (C++)

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

2

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
JonS
  • 621
  • 7
  • 25
2

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
    // ....
}
tuket
  • 3,232
  • 1
  • 26
  • 41
  • This is much better handled using RAII idioms. I know the blog you reference says it is inconvenient writing a throwaway class, but `std::unique_ptr` solve that problem using a custom deleter. – Matt Eding Jul 14 '21 at 21:24
  • @MattEding Well, this is already using RAII idiom, in some way. The blog doesn't say that is incovenient. – tuket Jul 15 '21 at 10:05
  • 1
    True, it uses RAII in the implementation, but the manual call afterward seems to defeat the spirit of it. The blog implies inconvenience with: "You may say that RAII in C++ solves this issue but this would require a class wrapper. defer allows for the same thing as RAII but without manually creating a wrapper type." – Matt Eding Jul 15 '21 at 21:40
  • @MattEding I don't see that implication in the sentence, maybe you just see the inconvenience by yourself :) – tuket Jul 16 '21 at 08:08
1

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; }
}
Amos
  • 3,238
  • 4
  • 19
  • 41
1

__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.

Kaz
  • 55,781
  • 9
  • 100
  • 149
0

__COUNTER__ is guaranteed to be unique unlike __LINE__. Some compilers allow __LINE__ to be reset. #include files will also reset __LINE__.

BSalita
  • 8,420
  • 10
  • 51
  • 68
  • 5
    All standard C and C++ compilers are required to provide the feature that resets `__LINE__`. – Potatoswatter Jan 25 '15 at 12:38
  • But `__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. – Kaz Apr 07 '22 at 21:32
0

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.

Devolus
  • 21,661
  • 13
  • 66
  • 113
0

__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
SSpoke
  • 5,656
  • 10
  • 72
  • 124
0

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.

Matt Eding
  • 917
  • 1
  • 8
  • 15
0

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")
johnjohnlys
  • 394
  • 1
  • 9
0

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.

Sz.
  • 3,342
  • 1
  • 30
  • 43
-2

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.

thegreendroid
  • 3,239
  • 6
  • 31
  • 40
  • 4
    `__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. – Mooing Duck Feb 17 '15 at 01:50