0

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.

szefany
  • 9
  • 2
  • What is `AddVariable` supposed to do? – Anton Savin Dec 17 '14 at 14:40
  • 3
    `#define ASDF ++counter` will not do what you want anyway – Tavian Barnes Dec 17 '14 at 14:40
  • 3
    The preprocessor is a *compile-time* thing, and is handled as a separate step before the actual compilation, therefore you can't do anything using the preprocessor during runtime. – Some programmer dude Dec 17 '14 at 14:41
  • 1
    Please don't do this.. – Lawrence Aiello Dec 17 '14 at 14:45
  • 7
    This looks like an [x-y problem](http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem). – molbdnilo Dec 17 '14 at 14:46
  • 1
    I assume you could chain #defines in *different* preprocessor directives. I always get confused with it so I'd just go and experiment, if in doubt with gcc -E. – Peter - Reinstate Monica Dec 17 '14 at 14:49
  • @JoachimPileborg seems to have a (better?) idea of what you are trying to achieve at all. Can you elaborate? – Peter - Reinstate Monica Dec 17 '14 at 14:52
  • Is there any reason `int const ABCD = ++counter;` can't be used? (Of course, `ABCD` will _not_ be a constant integral expression in this case.) – James Kanze Dec 17 '14 at 14:57
  • @JamesKanze I want it to be flexible. If we have another class that extends the Base class, we may add new variables in the new class. – szefany Dec 17 '14 at 15:12
  • @JoachimPileborg I realized that, but is there a better way to keep flexible in the subclass which extends the Base class and is able to add its own variables? – szefany Dec 17 '14 at 15:15
  • @AntonSavin The subclass which extends the Base class may add its own variables. – szefany Dec 17 '14 at 15:27
  • 1
    What are the lifetimes/scopes of `ASDF`/`HJKL` supposed to be? Are they supposed to be members of `Base`? Globals in your cpp? What calls `AnotherHandler()`? – Julian Dec 17 '14 at 15:53
  • 1
    @szefany And... What problem are you trying to solve? – James Kanze Dec 17 '14 at 17:13
  • @AtlasC1 Sorry for the ambiguous description. I've updated the problem, it might be a bit clearer now. – szefany Dec 17 '14 at 18:27
  • @JamesKanze Actually the added variables stands for some states, each with a specific handler (we may use a map as a reflection). That is, in the subclass we are allowed to add new states and new handlers rather than in the base class. But the variables should be shared so that they can be called in different handlers. – szefany Dec 17 '14 at 18:33
  • http://stackoverflow.com/questions/6166337/does-c-support-compile-time-counters – didierc Dec 18 '14 at 16:43

3 Answers3

1

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
    }
}
Jonathan Mee
  • 37,899
  • 23
  • 129
  • 288
1

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
Julian
  • 1,688
  • 1
  • 12
  • 19
  • I guess "Add" in the question doesn't really mean "add"; it rather means "increase" (add 1 to the value of the variable); I don't know for sure though; seems vague. – anatolyg Dec 17 '14 at 16:29
  • @anatolyg It's "add" indeed; the codes here might be a bit ambiguous. It should be "adding a new constant variable/label assigned to a specific value", and that value is controlled by the increasing counter. – szefany Dec 17 '14 at 18:39
  • @szefany Does my modified answer better suit your needs? If not, what else does it need to do? – Julian Dec 17 '14 at 19:44
0

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)

Community
  • 1
  • 1
Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547