C++ 有没有人使用过 __COUNTER__ 预处理器宏?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/652815/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 16:31:29  来源:igfitidea点击:

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

c++c

提问by dcw

The __COUNTER__symbol is provided by VC++and GCC, and gives an increasing non-negative integral value each time it is used.

__COUNTER__符号由VC++和 GCC 提供,每次使用时都会给出一个递增的非负整数值。

I'm interested to learn whether anyone's ever used it, and whether it's something that would be worth standardising?

我很想知道是否有人曾经使用过它,以及它是否值得标准化?

采纳答案by JamieH

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

它用于xCover代码覆盖库中,用于标记执行通过的行,以查找未覆盖的行。

回答by

__COUNTER__is useful anywhere you need a unique name. I have used it extensively for RAII style locks and stacks. Consider:

__COUNTER__在需要唯一名称的任何地方都很有用。我已经将它广泛用于 RAII 样式的锁和堆栈。考虑:

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_use4or 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__:

命名锁的用途会变得很乏味,如果它们没有全部在块的顶部声明,甚至可能成为错误的来源。你怎么知道你是在lock_use4还是在lock_use11?这也是对命名空间的不必要的污染——我从不需要通过名称来引用锁使用对象。所以我使用__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.

但是不要因为我称对象锁而被挂断了 - 任何需要在匹配对中调用的函数都适合这种模式。您甚至可能对给定块中的同一个“锁”有多种用途。

回答by Charlie Martin

I've never used it for anything but a DEBUG macro. It's convenient to be able to say

除了 DEBUG 宏之外,我从未将它用于任何其他用途。方便的话可以说

#define WAYPOINT \
    do { if(dbg) printf("At marker: %d\n", __COUNTER__); } while(0);

回答by Michael Burr

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

我在编译时断言宏中使用它,让宏为唯一的 typedef 创建名称。看

if you want the gory details.

如果你想要血腥的细节。

回答by Potatoswatter

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.

是的,但正如您从本问答中的许多示例中看​​到的那样__LINE__,标准化的 ,在大多数情况下也足够了。

__COUNTER__is only really necessary in cases where the count must increase by one each time, or it must have continuity over several #includefiles.

__COUNTER__只有在计数必须每次增加一的情况下才真正有必要,或者它必须在多个#include文件上具有连续性。

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 .cppfiles (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.

__COUNTER__与 不同__LINE__, 非常危险,因为它取决于包含的头文件和顺序。如果两个.cpp文件(翻译单元)包含一个使用__COUNTER__的头文件,但头文件在不同的实例中得到的计数序列不同,则它们可能对同一事物使用不同的定义,违反了一个定义规则。

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.

违反单一定义规则的行为非常难以捕捉,并且可能会产生错误和安全风险。的少数用例__COUNTER__并没有真正超过缺点和缺乏可扩展性。

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.

即使您从不发布使用 的代码__COUNTER__,它在对枚举序列进行原型设计时也很有用,省去了在成员资格具体化之前分配名称的麻烦。

回答by StaceyGirl

It is used by Boost.Asio to implement stackless coroutines.

Boost.Asio 使用它来实现无堆栈协程。

See this header fileand examples.

请参阅此头文件示例

Resulting coroutines look like this:

生成的协程如下所示:

struct task : coroutine
{
  ...
  void operator()()
  {
    reenter (this)
    {
      while (... not finished ...)
      {
         ... do something ...
         yield;
         ... do some more ...
         yield;
       }
     }
   }
   ...
};

回答by Leonard

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.

如果我正确理解了该功能,我希望我在 Perl 中工作时拥有该功能,将事件记录功能添加到现有 GUI 中。我想确保所需的手动测试(叹气)为我们提供了完整的覆盖范围,因此我将每个测试点记录到一个文件中,并记录一个__counter__值可以轻松查看覆盖范围中缺少的内容。照原样,我手工编写了等效代码。

回答by Francis Xavier

I've used it to generate unique types in this article: http://www.codeproject.com/Articles/42021/Sealing-Classes-in-C

我在这篇文章中用它来生成独特的类型:http: //www.codeproject.com/Articles/42021/Sealing-Classes-in-C

回答by BSalita

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

__COUNTER__保证是唯一的,不像__LINE__. 一些编译器允许__LINE__重置。#include 文件也将重置__LINE__

回答by thegreendroid

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.

我打算使用__COUNTER__给我们代码库中的每个文件一个唯一标识符,以便该唯一代码可用于在嵌入式系统中记录 ASSERT。

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 Yourselfon Embedded.com. It's a shame that it only works with GCC-based compilers though.

这种方法比使用字符串存储文件名(使用__FILE__)高效得多,尤其是在具有微小 ROM 的嵌入式系统上。我在阅读这篇文章时想到了这个想法 -在 Embedded.com 上断言。遗憾的是它只适用于基于 GCC 的编译器。