*/ } ul /* Whole unordered list */ { } ul li /* Unordered list item */ { } ol /* Whole ordered list */ { } ol li /* Ordered list item */ { } hr {} /* ---- Some span elements --- */ sub /* Subscripts. Pandoc: H~2~O */ { } sup /* Superscripts. Pandoc: The 2^nd^ try. */ { } em /* Emphasis. Markdown: *emphasis* or _emphasis_ */ { } em > em /* Emphasis within emphasis: *This is all *emphasized* except that* */ { font-style: normal; } blockquote > p > em /* Emphasis within emphasis: *This is all *emphasized* except that* */ { font-style: normal; } blockquote > * > p > em /* Emphasis within emphasis: *This is all *emphasized* except that* */ { font-style: normal; } blockquote > p > ins > em /* Emphasis within emphasis: *This is all *emphasized* except that* */ { font-style: normal; } blockquote > * > p > ins > em /* Emphasis within emphasis: *This is all *emphasized* except that* */ { font-style: normal; } /* ---- Links (anchors) ---- */ a /* All links */ { /* Keep links clean. On screen, they are colored; in print, they do nothing anyway. */ text-decoration: none; } @media screen { a:hover { /* On hover, we indicate a bit more that it is a link. */ text-decoration: underline; } } @media print { a { /* In print, a colored link is useless, so un-style it. */ color: black; background: transparent; } a[href^="http://"]:after, a[href^="https://"]:after { /* However, links that go somewhere else, might be useful to the reader, so for http and https links, print the URL after what was the link text in parens */ content: " (" attr(href) ") "; font-size: 90%; } } /* ---- Images ---- */ img { /* Let it be inline left/right where it wants to be, but verticality make it in the middle to look nicer, but opinions differ, and if in a multi-line paragraph, it might not be so great. */ vertical-align: middle; } div.figure /* Pandoc figure-style image */ { /* Center the image and caption */ margin-left: auto; margin-right: auto; text-align: center; font-style: italic; } p.caption /* Pandoc figure-style caption within div.figure */ { /* Inherits div.figure props by default */ } /* ---- Code blocks and spans ---- */ pre, code { background-color: #fdf7ee; /* BEGIN word wrap */ /* Need all the following to word wrap instead of scroll box */ /* This will override the overflow:auto if present */ white-space: pre-wrap; /* css-3 */ white-space: -moz-pre-wrap !important; /* Mozilla, since 1999 */ white-space: -pre-wrap; /* Opera 4-6 */ white-space: -o-pre-wrap; /* Opera 7 */ word-wrap: break-word; /* Internet Explorer 5.5+ */ /* END word wrap */ } pre /* Code blocks */ { /* Distinguish pre blocks from other text by more than the font with a background tint. */ padding: 0.5em; /* Since we have a background color */ border-radius: 5px; /* Softens it */ /* Give it a some definition */ border: 1px solid #aaa; /* Set it off left and right, seems to look a bit nicer when we have a background */ margin-left: 0.5em; margin-right: 0.5em; } pre.yacc, code.yacc { background-color: #f0f0f0; } pre.yacc /* Code blocks */ { /* Distinguish pre blocks from other text by more than the font with a background tint. */ padding: 0.0em; /* Since we have a background color */ border-radius: 5px; /* Softens it */ /* Give it a some definition */ border: 0px solid #aaa; /* Set it off left and right, seems to look a bit nicer when we have a background */ margin-left: 0.0em; margin-right: 0.0em; } @media screen { pre { white-space: pre; /* Dotted looks better on screen and solid seems to print better. */ border: 1px dotted #777; } } code /* All inline code spans */ { } p > code, li > code /* Code spans in paragraphs and tight lists */ { /* Pad a little from adjacent text */ padding-left: 2px; padding-right: 2px; } li > p code /* Code span in a loose list */ { /* We have room for some more background color above and below */ padding: 2px; } span.option { color: blue; text-decoration: underline; } /* ---- Math ---- */ span.math /* Pandoc inline math default and --jsmath inline math */ { /* Tried font-style:italic here, and it messed up MathJax rendering in some browsers. Maybe don't mess with at all. */ } div.math /* Pandoc --jsmath display math */ { } span.LaTeX /* Pandoc --latexmathml math */ { } eq /* Pandoc --gladtex math */ { } /* ---- Tables ---- */ /* A clean textbook-like style with horizontal lines above and below and under the header. Rows highlight on hover to help scanning the table on screen. */ table { border-collapse: collapse; border-spacing: 0; /* IE 6 */ border-bottom: 2pt solid #000; border-top: 2pt solid #000; /* The caption on top will not have a bottom-border */ /* Center */ margin-left: auto; margin-right: auto; } thead /* Entire table header */ { border-bottom: 1pt solid #000; background-color: #eee; /* Does this BG print well? */ } tr.header /* Each header row */ { } tbody /* Entire table body */ { } /* Table body rows */ tr { } tr.odd:hover, tr.even:hover /* Use .odd and .even classes to avoid styling rows in other tables */ { background-color: #eee; } /* Odd and even rows */ tr.odd {} tr.even {} td, th /* Table cells and table header cells */ { vertical-align: top; /* Word */ vertical-align: baseline; /* Others */ padding-left: 0.5em; padding-right: 0.5em; padding-top: 0.2em; padding-bottom: 0.2em; } /* Removes padding on left and right of table for a tight look. Good if thead has no background color*/ /* tr td:last-child, tr th:last-child { padding-right: 0; } tr td:first-child, tr th:first-child { padding-left: 0; } */ th /* Table header cells */ { font-weight: bold; } tfoot /* Table footer (what appears here if caption is on top?) */ { } caption /* This is for a table caption tag, not the p.caption Pandoc uses in a div.figure */ { caption-side: top; border: none; font-size: 0.9em; font-style: italic; text-align: center; margin-bottom: 0.3em; /* Good for when on top */ padding-bottom: 0.2em; } /* ---- Definition lists ---- */ dl /* The whole list */ { border-top: 2pt solid black; padding-top: 0.5em; border-bottom: 2pt solid black; } dt /* Definition term */ { font-weight: bold; } dd+dt /* 2nd or greater term in the list */ { border-top: 1pt solid black; padding-top: 0.5em; } dd /* A definition */ { margin-bottom: 0.5em; } dd+dd /* 2nd or greater definition of a term */ { border-top: 1px solid black; /* To separate multiple definitions */ } /* ---- Footnotes ---- */ a.footnote, a.footnoteRef { /* Pandoc, MultiMarkdown footnote links */ font-size: small; vertical-align: text-top; } a[href^="#fnref"], a.reversefootnote /* Pandoc, MultiMarkdown, ?? footnote back links */ { } @media print { a[href^="#fnref"], a.reversefootnote /* Pandoc, MultiMarkdown */ { /* Don't display these at all in print since the arrow is only something to click on */ display: none; } } div.footnotes /* Pandoc footnotes div at end of the document */ { } div.footnotes li[id^="fn"] /* A footnote item within that div */ { } table tr td,th { border-right: 1px solid; border-left: 1px solid; } /* You can class stuff as "noprint" to not print. Useful since you can't set this media conditional inside an HTML element's style attribute (I think), and you don't want to make another stylesheet that imports this one and adds a class just to do this. */ @media print { .noprint { display:none; } }
__COUNTER__
predefined macro2025-01-25
integration into IS ISO/IEC 9899:202y
document number | date | comment |
---|---|---|
n3457 | 202501 | Original proposal |
CC BY, see https://creativecommons.org/licenses/by/4.0
The __COUNTER__
predefined macro is
a common language extension for C and C++ which expands to an integer
literal that starts at 0
and increments by
1
every time
it is expanded in a translation unit. This is useful for generating
unique identifiers, generating unique indices, and other preprocessor
metaprogramming uses. We propose standardizing the macro and its
semantics.
A standalone paper for __COUNTER__
has not been presented to WG14, however, it was briefly mentioned in,
Extensions to the preprocessor for C2Y, n3190.
This paper provides a focused proposal on __COUNTER__
and aims to provide additional
context and motivation. It originates from a discussion in the C-C++
liaison SG of C++ paper P3384
as submitted to WG21.
__COUNTER__
is de-facto portable
today. Most implementations support it with unsurprising semantics.
However, there is inherent uncertainty surrounding portability and
semantics due to it not being standardized.
Consequently, codebases striving for maximum portability must resort to detection and fallback such as this example from google benchmark:
// Check that __COUNTER__ is defined and that __COUNTER__ increases by 1
// every time it is expanded. X + 1 == X + 0 is used in case X is defined to be
// empty. If X is empty the expression becomes (+1 == +0).
#if defined(__COUNTER__) && (__COUNTER__ + 1 == __COUNTER__ + 0)
#define BENCHMARK_PRIVATE_UNIQUE_ID __COUNTER__
#else
#define BENCHMARK_PRIVATE_UNIQUE_ID __LINE__
#endif
Meanwhile other C and C++ codebases avoid the macro altogether due to
this uncertainty. In the absence of cautious checking and fallback, a
developer must consult numerous widely used implementations to convince
themselves that __COUNTER__
exists and
behaves as they expect.
In the case of google benchmark, __LINE__
is an adequate fallback due to how
BENCHMARK
macros are typically used.
However, this is not an adequate general-purpose replacement due to it
not being unique in the general case.
While every major C++ compiler today supports __COUNTER__
, it’s not always enabled. For
example, EDG only provides it outside of standards mode.
Additionally, minor divergences in __COUNTER__
semantics are observable (see Number of Expansions), though they do
not impact most use cases.
Due to fairly widespread use in both C and C++ it would be useful to
incorporate the existing practice of __COUNTER__
into the official standard in
order to provide more clear portability and semantic guarantees.
A brief survey of some uses of __COUNTER__
in C and C++:
C:
__COUNTER__
for, among
other things:
__COUNTER__
for
unique identifiers in multiple places link
1 link
2__COUNTER__
for unique
identifiers__COUNTER__
auto-incrementing endpoint
numbers; link__COUNTER__
for unique indices in timing
utilities; link__COUNTER__
for unique identifiers througout
the codebase; link__COUNTER__
for lookup
tables as part of a localization and compile-time string hashing
system.Many additional uses include use for static assertions, however, that use case is now covered by C11 and C23 static assertion facilities.
C++:
__COUNTER__
for unique
identifiers, falling back to __LINE__
if __COUNTER__
isn’t present or doesn’t behave
as expected__COUNTER__
for
unique
identifiers__COUNTER__
for unique
identifiers as well as in sanitizer code to prevent
ICF__COUNTER__
for unique
identifiers, falling back to __LINE__
__COUNTER__
extensively, primarily for unique
identifiers__COUNTER__
for
unique identifier generation, e.g. in crash
logging code, as well as for creating
unique
tags for ABORT()
s__COUNTER__
for unique
identifiers, falling back to __LINE__
if not present__COUNTER__
for unique
identifiersAll major C and C++ compilers support __COUNTER__
as well as most C compilers
available on Compiler Explorer:
Compiler explorer comparison with earliest supported versions available https://godbolt.org/z/Mx4MznMaY
Our suggested wording below takes several points that could present difficulties into account.
There are a few edge cases where implementations diverge in what is
considered to be an expansion of the __COUNTER__
macro. Currently, without the
addition of __COUNTER__
it is not
observable if macro parameters are expanded only once (and then inserted
in the replacement list) or if such an expansion is performed at each
point of insertion. __COUNTER__
changes this, because it introduces a side effect into
preprocessing.
We propose a parameter be expanded only once, which is the current behavior of almost all compilers tested on Compiler Explorer:
Similarly, if the parameter is never used no expansion should occur:
Additionally, __VA_OPT__
should be
considered to expand __VA_ARGS__
even if
__VA_ARGS__
is
unused. This is for ease of implementation and is the current behavior
on GCC and MSVC but not Clang:
Notably, Clang produces the desired output in the following example:
The stringizing operator and token pasting operator should not cause expansion. This is the current behavior on all compilers tested on compiler explorer.
#define STR(X) #X
STR(__COUNTER__) // "__COUNTER__"
#define CONCAT(X) A##X
CONCAT(__COUNTER__) // A__COUNTER__
__COUNTER__ // 0
#define CONCAT2(X) A##X X
CONCAT2(__COUNTER__) // A__COUNTER__ 1
__COUNTER__ // 2
We think that the text that regulates expansion of macro parameters should be adapted, such as to remove these ambiguities. This is proposed for clause 6.10.5.2. Here, we now distinguish the parameter name itself more clearly from its potentially multiple appearances in the replacement list and insist that the parameter is expanded at most once, and then spliced into the overall macro expansion at each of its occurrences.
We propose to proceed analogously to the __LINE__
macro and the #line
directive. For
the latter a fixed bound for the line number of 231-1 (which
is 2147483647) is established, so we just copy that value for the bound
on __COUNTER__
.
If stepped over, such an upper bound should still not result in new UB for the preprocessor. Since it is easily detectable that the value overflows over the given limit, we constrain implementations to diagnose situations where such an overflow happens.
If not we would introduce a new UB into the preprocessor.
If not, we could
LONG_MAX
, but then we should
probably also change the limit for #line
to that
value<limits.h>
that holds the limit.Existing practice is that __COUNTER__
expands as a simple base-10
integer literal with no digit separators or suffixes. This could lead to
surprising behavior where different expansions of __COUNTER__
have different types, such as
32767
(signed
) and 32768
(long
) on a system
with an INT_WIDTH
of 16
. There are three
options to address this:
__COUNTER__
if their use is sensitive to the
typeWe do not propose constraining whether an implementation can expand
__COUNTER__
with a suffix. On small
freestanding systems it could well make sense to add a L
or U
suffix, such that a wider spectrum of values without type change is
produced.
On the other hand, integer literals now could contain digit
separators (’ characters). If so, such a number would not be composable
with identifiers by means of the ##
operator. Thus we
exclude this form of integer literals.
If yes, that would deviate significantly from the analog definition
for __LINE__
.
If yes, that would again deviate from the analog definition for __LINE__
where no restriction is made.
Note to the editors: When we extended the term
integer-literal for C23, it seems that we forgot to disallow
digit separators for __LINE__
.
__COUNTER__
and the C libraryMany implementations already have the macro as an extension. Since
this is not otherwise regulated, implementations of the C library might
use it to generate unique identifiers, for example for local variables
in type-generic atomic macros or for parameter names of function
interfaces. Therefore we think that the C library should not be
constrained in using the __COUNTER__
macro and we propose to make this explicit in the text.
New text is underlined green, removed text is
stroke-out red.
Modify p4
Semantics
4 After the arguments for the invocation of a function-like macro have been identified, argument substitution takes place. A va-opt-replacement is treated as if it were a parameter. For each parameter that occurs in the replacement list
that issuch that it is neither preceded by a#
or##
preprocessing token nor followed by a##
preprocessing token, the preprocessing tokens naming the parameter are replaced by a token sequence determined as follows:
— If the parameter is of the form va-opt-replacement, the replacement preprocessing tokens are the preprocessing token sequence for the corresponding argument, as specified later in this subclause.
— Otherwise, the replacement preprocessing tokens are the preprocessing tokens of the corresponding argument after all macros contained therein have been expanded. The argument’s preprocessing tokens are completely macro replaced before being substituted as if they formed the rest of the preprocessing file with no other preprocessing tokens being available. For each such parameter this expansion is performed exactly once, and then preprocessing tokens naming the parameter are each replaced with the resulting token list.
The values of the predefined macros listed in the following subclauses216) (except for
__COUNTER__
,__FILE__
and__LINE__
) remain constant throughout the translation unit.
add an item to the list
__COUNTER__
a per-expansion unique
integer literal as described in 6.10.10.2.1.
6.10.10.2.1 The __COUNTER__
predefined macro
Description
1 The expansion of the object-like macro__COUNTER__
produces a unique integer literal not containing any digit separators that relates to the specific lexical position within the pp-token sequence during translation phase 4. The produced integer literal is such that a concatenation with a preceding identifier token using the##
operator again results in an identifier token, and such that when interpreted in translation phase 7 it has a value that is representable with thesigned long
type. The value of the first expansion in a given translation unit is zero, and each subsequent expansion produces a value that is one greater than the previous one.
2 It is unspecified if the inclusion of any of the standard headers of
clause 7 or if the invocations of any macro that is defined by them will
result in expansions of the __COUNTER__
macro.
Constraints
3 The number of expansions of the__COUNTER__
macro in a translation unit shall not exceed2147483647
.
Recommended practice
4 It is recommended that implementations either
- diagnose an invocation of the
__COUNTER__
macro that produces a literal that, if interpreted in translation phase 7, has a type that is different from the previous invocation, or- ensure that all resulting integer literals have the same type in translation phase 7, for example by appending the suffix
L
.
Application code should not make other assumptions than given in the description about the form, type or value of the integer literal that is produced.
5 EXAMPLE The __COUNTER__
predefined macro is useful for
producing unique identifiers:
#define CONCAT_IMPL(A, B) A ## B
#define CONCAT(A, B) CONCAT_IMPL(A, B)
#define UNIQUE_ID(NAME) CONCAT(NAME, __COUNTER__)
#define SWAP_IMPL(A, B, PTRA, PTRB, TMP) \
do { \
auto PTRA = &(A); \
auto PTRB = &(B); \
auto TMP = *PTRA; \
*PTRA = *PTRB; \
*PTRB = TMP; \
} while (false)
/* A and B are modifiable and addressable lvalues. */
#define SWAP(A, B) \
SWAP_IMPL(A, B, \
UNIQUE_ID(ptr), \
UNIQUE_ID(ptr), \
UNIQUE_ID(val))
If__COUNTER__
has not been expanded earlier in the translation unit, invokingSWAP(X[35], y)
expands to
do {
auto ptr0 = &(X[35]);
auto ptr1 = &(y);
auto val2 = *ptr0;
*ptr0 = *ptr1;
*ptr1 = val2;
} while (false)
or similar. Here, the produced identifiers not only depend on the number
of previous expansions of __COUNTER__
but also on the specific form of integer literal that the implementation
provides.
add a new bullet point at the end
— It is unspecified if the inclusion of any of the standard headers or
if the invocation of any macro defined in these headers invokes the
predefined macro __COUNTER__
even
multiple times.
Thanks to … for review and discussions.