Reputation: 9
The previous problem description was ambiguous, so I modified something below. Thanks.
I want to implement some macros like this:
#define AddVariable(x) \
#define x (++counter)
class Base {
private:
int counter = 0;
}
class Extend : public Base {
public:
void Handler() {
AddVariable(ASDF);
AddVariable(HJKL);
// Here may add more variables.
}
void AnotherHandler() {
// It calls ASDF, HJKL too.
}
}
The ASDF and HJKL should be available through all handlers in the cpp file, so I have to define it in the macro (it's not a good design, though). But how should I write the proper macros to achieve it (#define cannot be nested in another #define)? Or is there another better way of implementation?
Thanks in advance.
Update:
A potential implementation is
#define AddVariable(x) \
int x = ++counter;
It works, but x is not global, and I have to fix this.
Upvotes: 0
Views: 547
Reputation: 1
You cannot do that (defining a macro in a macro) with the C preprocessor.
However, sometimes you could play X-macro tricks, like here.
If you really need macro defining macros, switch to some external or non-standard preprocessor, like GNU m4 or gpp.
Alternatively, generate your C++ code with some external tool (e.g. your own Python or GNU awk script)
At last, recent GCC (e.g. GNU cpp) or Clang/LLVM offer the __COUNTER__
macro (also usable indirectly with stringification & concatenation)
Upvotes: 0
Reputation: 1736
Would using an std::map
work?
#include <iostream>
#include <map>
#include <string>
class Base {
protected:
void AddVariable(const std::string& name) {
variables[name] = counter++;
}
int& GetVariable(const std::string& name) {
return variables[name];
}
private:
int counter = 0;
std::map<std::string, int> variables;
};
class Extend : Base {
public:
void Handler() {
AddVariable("ASDF");
AddVariable("HJKL");
// May add more variables here ...
}
void AnotherHandler() {
// Use ASDF, HJKL here too
std::cout << GetVariable("ASDF") << std::endl;
std::cout << GetVariable("HJKL") << std::endl;
}
};
int main()
{
Extend e;
e.Handler();
e.AnotherHandler();
}
Output:
0
1
Upvotes: 1
Reputation: 38919
It looks like you are trying to expose an incrementer to a Base
object's counter
to all of your functions in the .cpp file.
Answer: This is not possible.
The other functions/objects in your .cpp file do not have a reference to a Base
object and thereby cannot change any of it's data.
If you want to maintain a single counter for all the Base
objects you might try something like this:
class Base {
public:
static void ASDF(){counter++;}
private:
static int counter = 0;
};
This can be called from and other function:
void AnotherHandler() {
Base::ASDF();
}
EDIT:
class Base {
protected:
static int counter = 0;
};
class Another : public Base{
public:
Another(){
counter++; // As a child of Base you have access to all of it's protected variables
}
}
Upvotes: 1