szefany
szefany

Reputation: 9

How to implement a #define in another #define?

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

Answers (3)

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

Julian
Julian

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

Jonathan Mee
Jonathan Mee

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

Related Questions