Repeated Class Instantiation without using Identifier - c++

I want to repeatedly instantiate a class, within module scope, without providing a unique name. Something like this.
MyClass name##__LINE__(); // doesn't work because __LINE__ won't stringify
MyClass name##__LINE__(); // duplicate identifier error - two name__LINE__ variables
Is there some way to do this, either creating a unique name or using some anonymous context, such as an initializer or struct?

See this answer
#define CONCATENATE_DETAIL(x, y) x##y
#define CONCATENATE(x, y) CONCATENATE_DETAIL(x, y)
#define MAKE_UNIQUE(x) CONCATENATE(x, __LINE__)
MyClass MAKE_UNIQUE(name);
MyClass MAKE_UNIQUE(name);
...
Or just make an array:
MyClass arr[N];
Why these macros work
C11 standard, 6.10.3.1 Argument substitution:
After the arguments for the invocation of a function-like macro have been identified,
argument substitution takes place. A parameter in the replacement list, unless preceded
by a # or ## preprocessing token or followed by a ## preprocessing token (see below), is
replaced by the corresponding argument after all macros contained therein have been
expanded. Before being substituted, each argument’s preprocessing tokens are
completely macro replaced as if they formed the rest of the preprocessing file; no other
preprocessing tokens are available.
Corresponding paragraph in C++ standard (16.3.1 Argument substitution) is exact copy of C standard's.

You need to double nest the concatenation operator
struct A{};
#define JOIN(X, Y) JOIN_DETAIL(X, Y)
#define JOIN_DETAIL(X, Y) JOIN_DETAIL2(X, Y)
#define JOIN_DETAIL2(X, Y) X##Y
int main() {
A JOIN(a, __LINE__);
A JOIN(a, __LINE__);
}

Related

Why is token replacement done before macro expansion?

Considering the following snippet:
#include <stdio.h>
#define MY_MACRO(\
arg) \
arg
#define MY_MACRO2(t1, t2) t1##t2
#define MY_ a
#define MACRO b
int main() {
printf("%d\n", MY_MACRO2(MY_,MACRO)(45));
return 0;
}
It turns out to compile and display 45, however, if MY_ and MACRO were expanded before substitution, this code should not compile.
The reason why I notice this is when I read in the C standard the following:
6.10.3.1 (but also in C++ standard)
After the arguments for the invocation of a function-like macro have been identified,argument substitution takes place.A parameter in the replacement list, unless preceded by a # or ## preprocessing token or followed by a ## preprocessing token (see below), is replaced by the corresponding argument after all macros contained therein have been expanded. Before being substituted, each argument’s preprocessing tokens are completely macro replaced as if they formed the rest of the preprocessing file; no other preprocessing tokens are available
So if all macros contained in the arguments were expanded before replacement, why don't we end up with ab(45)?
To let constructions like X(X()) work. Note that while X() is expanded the X macro is disabled to avoid infinite recursions. Expanding arguments before expanding the macro let's one use X in the arguments.
A practical application of X(X()):
#define TEN(x) x x x x x x x x x x
#define HUNDRED(x) TEN(TEN(x))

Nested macro expansion

I'm not sure if that's the right terminology to use, however my problem is that the a macro call ("PLUGIN_NAME") as a parameter to another macro call ("IMPLEMENT_MODULE"), which in turn prints it as a string, prints that argument as the macro call ("somePLUGIN_NAME") rather than the expanded result ("someSomePluginName").
Note that "IMPLEMENT_MODULE" is an API call so I can't change that.
#define IMPLEMENT_MODULE(name) something##name
#define PLUGIN_NAME SomePluginName
#define _STR(s) #s
#define STR(s) _STR(s)
#define PLUGIN_NAME_STR STR(PLUGIN_NAME)
int main()
{
string expected = "somethingSomePluginName";
string actual = STR(IMPLEMENT_MODULE(PLUGIN_NAME));
printf("expected: %s || actual: %s\n", expected.c_str(), actual.c_str());
assert(expected == actual);
}
I've put it here:
http://codepad.org/FRzChJtD
You need another helper macro to concatenate the preprocessor tokens after macro-expanding them:
#define IMPLEMENT_MODULE_2(A, B) A##B
#define IMPLEMENT_MODULE(name) IMPLEMENT_MODULE_2(something, name)
See working example here
This technical explanation is that macro expansion will not occur if the token-pasting (##) or stringizing operator (#) are found by the preprocessor.

How to compose valid token depending on pre-defined macros (C++ preprocessor)?

Suppose some tokens FOO, BAR, and DUD (and possibly more) are #defined or not. I would like to have a macro EXTEND(name) that generates a valid extended name, e.g.
#define FOO
#undef BAR
#define DUD
EXTEND(object)
expands to
object_foo_dud
Is it possible to write macro EXTEND with less than O(2n) lines if there are n macro tokens (like FOO, BAR, and DUD)? I think it should be possible with O(n) lines, but how?
I've tried this:
#ifdef FOO
# define ExtFOO(name) name ## _foo
#else
# define ExtFOO(name) name
#endif
#ifdef BAR
# define ExtBAR(name) ExtFOO(name) ## _bar
#else
# define ExtBAR(name) ExtFOO(name)
#endif
#ifdef DUD
# define ExtDUD(name) ExtBAR(name) ## _dud
#else
# define ExtDUD(name) ExtBAR(name)
#endif
#define EXTEND(name) ExtDUD(name)
but
test.cc:26:5: error: pasting formed ')_dud', an invalid preprocessing token
EXTEND(object)
^
The ## operator concatenates two preprocessing tokens and must yield a single valid token. For example, from section 6.10.3.3 of the C99 spec:
For both object-like and function-like macro invocations, before the replacement list is
reexamined for more macro names to replace, each instance of a ## preprocessing token
in the replacement list (not from an argument) is deleted and the preceding preprocessing
token is concatenated with the following preprocessing token. Placemarker preprocessing tokens are handled specially: concatenation of two placemarkers results in a single placemarker preprocessing token, and concatenation of a placemarker with a non-placemarker preprocessing token results in the non-placemarker preprocessing token. If the result is not a valid preprocessing token, the behavior is undefined. The resulting token is available for further macro replacement. The order of evaluation of ## operators is unspecified.
So the expansion ExtBAR(name) ## _dud is invalid since it would yield ExtBAR(object)_dud.
I'd go with the following approach:
#ifdef FOO
# define ValFOO _foo
#else
# define ValFOO
#endif
#ifdef BAR
# define ValBAR _bar
#else
# define ValBAR
#endif
#ifdef DUD
# define ValDUD _dud
#else
# define ValDUD
#endif
#define CONCAT(a, b, c, d) a ## b ## c ## d
#define XCONCAT(a, b, c, d) CONCAT(a, b, c, d)
#define EXTEND(name) XCONCAT(name, ValFOO, ValBAR, ValDUD)
The intermediate XCONCAT step is needed because macro arguments are not expanded if they're concatenated using ##.

__COUNTER__ in variable name

I have seen this question:
How to generate random variable names in C++ using macros?
with the following answer: https://stackoverflow.com/a/1675203/551045
And I've tried to implement it in clang.
Here is my declaration:
#define TRACE(stream) FuncTrace x#__COUNTER__ (llvm::errs(), "hallo", 1)
I tried all variations x##__COUNTER__; x ## __COUNTER__ and so on but none seem to work.
Could this be a clang bug? The clang help page says it has the __COUNTER__ macro.
In the end the macro I need something like this:
#define TRACE(stream) FuncTrace x#__COUNTER__ (stream, __FUNCTION__, __LINE__)
To concatenate two tokens into one you use the ## operator. The # operator is used to turn a token into a string.
x ## __COUNTER__ will just produce x__COUNTER__. You need to fully expand __COUNTER__ first. One possible method is add a few more indirections, e.g.
#define YTRACE(x, y) FuncTrace x##y (llvm::errs(), __FUNCTION__, __LINE__)
#define XTRACE(x, y) YTRACE(x, y)
#define TRACE(x) XTRACE(x, __COUNTER__)

## macro argument concatenation not working as I expected

Shouldn't this:
#define MOGSH_CONCAT (x,y) x##y
#define MOGSH_DOUBLE (a,b) MOGSH_CONCAT(a,b)
#define MOGSH_DEFINEPROC (p) MOGSH_DOUBLE(_gt,p) options_dialog::p;
MOGSH_DEFINEPROC(AssignMainForm);
happily expand to:
_gtAssignMainForm options_dialog::AssignMainForm;
Given that _gt is not defined, _gtAssignMainForm is:
typedef void (__stdcall *_gtAssignMainForm)();
and options_dialog is just a class where AssignMainForm is a static member.
Instead, in MSVC9, I get the error:
'a' : undeclared identifier
on the line containing
MOGSH_DEFINEPROC(AssignMainForm);
In the definition of a function-like macro there can be no whitespace between the macro name and the ( beginning the parameter list.
#define MOGSH_CONCAT(x,y) x##y
// ^ no whitespace allowed here
As you have it now (with whitespace), MOGSH_CONCAT is an object-like macro with a replacement list of (x,y) x##y, which is why you are getting such strange results.