Has anyone ever had a use for the __COUNTER__ pre-processor macro?

前端 未结 16 1513
有刺的猬
有刺的猬 2020-11-29 00:37

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

16条回答
  •  渐次进展
    2020-11-29 00:49

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

提交回复
热议问题