-1

A way to create random (actually sequentially numbered) variable names is demonstrated in the question How to generate random variable names in C++ using macros?.

However, it is not explained how such a generated name can be accessed later. Imagine a class declaration with a constructor. You need the same random name for the class name and the c-tor. Always using the generator macro just generates a new identifer and the compilation fails. Here's an example:

#define CONCAT_(x,y) x##y
#define CONCAT(x, y) CONCAT_(x, y)

#define DESCRIBE_IMPL CONCAT(DescribeImpl, __COUNTER__)
class DESCRIBE_IMPL {
public:
  DESCRIBE_IMPL() {}
};

I tried storing the current counter value somehow (e.g. enum { COUNTER = __COUNTER__ }, but using this enum always leads to the name DescribeImplCOUNTER instead of the variant with the counter value.

The Real Problem

What I'm trying to solve with this approach is a case where I have multiple definitions of the same class in different cpp files (generated from macros) and the linker complains about multiple symbols (ODR violation). I cannot change this approach without significantly change the usage pattern.

Mike Lischke
  • 48,925
  • 16
  • 119
  • 181
  • This trick is only viable for things where the name is a throwaway. What are you *really* trying to solve? You [seem to be asking about your perceived solution](https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem). – StoryTeller - Unslander Monica Apr 02 '19 at 11:27
  • 3
    What is the *real* problem you try to solve with a solution like this? For "sequentially numbered" variables, one usually uses arrays or similar data-structures. Having a set of otherwise equal variables or classes clutters up the code, making it hard to read, understand and maintain. Using macros to "create" these symbols does't make it better. – Some programmer dude Apr 02 '19 at 11:28
  • Youy guys are right, this is part of a bigger problem and I tried to leave out as much irrelevant as possible. This approach is one attempt to solve the real problem. Let me add some information in my question. – Mike Lischke Apr 02 '19 at 11:31
  • Macros are simple, single run string replacement. You can't call a macro from a macro. – user6556709 Apr 02 '19 at 11:35
  • I must say your clarification isn't too clear. Multiple definitions of the same class is okay. So long as the token sequence defining it is exactly the same. Do you have macros that affect the class definition? – StoryTeller - Unslander Monica Apr 02 '19 at 11:38
  • It goes too far for this question to explain all the details involved here. Actually, I have my answer (it's not possible), so whoever posts an answer telling this gets accepted. I can ask a new question with a changed scope later. – Mike Lischke Apr 02 '19 at 11:44
  • 1
    The built-in non-standard macro `__COUNTER__` is per *translation unit*, so if you use the macro in different translation units it will not help. I think you should delete this question, and try to come up with an [mcve] for a new question where you ask about your real and underlying problem instead. – Some programmer dude Apr 02 '19 at 11:44
  • 4
    Have you tried putting your class in your cpp files in the anonymous namespace? – Alan Birtles Apr 02 '19 at 11:54
  • Woot, that did the trick! Very cool. Please post this comment as answer. – Mike Lischke Apr 02 '19 at 11:58
  • I think [this page](https://wiki.sei.cmu.edu/confluence/display/cplusplus/DCL60-CPP.+Obey+the+one-definition+rule) explains it rather well and shows demonstrative examples – PeterT Apr 02 '19 at 12:02
  • You can concatentate `__FILE__` to the name to make it different in each cpp file. – stark Apr 02 '19 at 12:52
  • That won't work since a file name can contain path separators (and other special chars) which are invalid for identifiers. – Mike Lischke Apr 02 '19 at 13:57

1 Answers1

0

Since no one else wants to post the answer from the comments. (Examples from here)

The issues is that this violates the ODR:

// a.cpp
struct S {
  int a;
};

// b.cpp
class S {
public:
  int a;
};

One solution is put the definitions into an anonymous namespace in each file, preventing the linker from trying to re-conciliate the name with another translation unit.

// a.cpp
namespace {
struct S {
  int a;
};
}

// b.cpp
namespace {
class S {
public:
  int a;
};
}
PeterT
  • 7,981
  • 1
  • 26
  • 34