views:

622

answers:

4

Update 3:

Never mind. I kinda got what I was looking for. The following gives unique identifiers inside a class.

static const int _counter_start = __COUNTER__;
static const int val1 = __COUNTER__ - _counter_start;
static const int val2 = __COUNTER__ - _counter_start;

Update 2:

Boost Preprocessor

I will be implementing something akin to a message map with this functionality.

class a
{
...
    MAP_BEGIN()
    MAP_DECL...
    MAP_END()
...
};

The thing is, for each MAP_DECL, I need to expand the macro in 2 places.

class a
{    
    virtual void func()
    {        
        ...
        //does something with the decl declaration        
    }
    ...
    //also expand some stuff here    
}

Boost preprocessor should (theoretically) allow me to accumulate MAP_DECL into a sequence and expand it into func() at the end (while simultaneously expanding the class fields as we go).


Update 1:

I'm using the Boost Preprocessor library at the moment. I'm currently stuck creating a new macro variable/definition like the following every time I need to add something to the sequence.

I'm trying to expand Boost Preprocessor sequences and I'm stuck doing this at the moment

#define SEQ (w)(x)(y)(z) 
#define SEQ2 BOOST_PP_SEQ_PUSH_BACK(SEQ, a)


Original:

Suppose I have the following code

#define CUR 2
#define CUR CUR + 2

How do I force the 2nd line to use the value of CUR from the first line?

+4  A: 

Succinctly, you can't.

At the time when CUR is expanded (after the second #define), the preprocessor will replace an instance of CUR with CUR + 2, and 'blue paint' the name CUR (not expanding it any further). Thereafter, the C compiler sees CUR + 2, which most likely yields a compilation error.

Jonathan Leffler
+2  A: 

You can't do that, you can only #define each macro once, else the compiler will spill an error.

daniel
You can do that. At least with GCC in default mode, you simply get a warning about a non-benign macro redefinition, but the redefined value takes effect. `#define X 1 / #define X 2 / int main(){return X;}` (using / to represent new lines). On MacOS X, I get 2 lines of warning data (though it is arguably just one warning); the program links and runs and generates an exit status of 2.
Jonathan Leffler
+3  A: 

Even if you could do that, it's dangerous.
Example:

#define CUR 2
#define CUR CUR + 2
...
int x = CUR*4; // x = 2 + 2 * 4
Nick D
The output from the preprocessor is: `int x = CUR + 2*4;` which will normally not compile because there is no definition of the variable CUR.
Jonathan Leffler
@Jonathan Leffler, I assume that the preprocessor had no problem to redefine CUR as `2 + 2`
Nick D
If you wrote: #define CUR 2+2 for the second instance, then the compiler might whinge a bit (warn), but it would work. And then your warning about the missing parentheses, if spelled out, would be valid. But it wasn't what the question was originally asking about - not quite. (And, I confess, I'm no longer sure what the question **is** asking about now, after the two updates.)
Jonathan Leffler
+1  A: 

I tried doing something similar at one point (appending to boost preprocessor sequences). I hit the wall hard (because of what Jonathan said in his answer) and ended up doing completely different thing.

Later I found that boost MPL type sequences have same effective limitation (which totally makes sense, but sometimes you don't see a wall until you actually bump into it :)).

You pretty much must define whole sequence or give it different name.

You are probably defining some member variable and then doing things with it in the function (registering?). If you keep messages in a container, you can make your MAP_DECL add a message into it, and then in the function just do a for loop.

#define MAP_BEGIN std::vector<Message> m_messages; \
  void buildMap() {
#define MAP_END }
#define MAP_DECL(...) m_messages.push_back(...);

If each message is of separate type, try type erasure (boost::any) or make them inherit from some base class and store that.

Eugene
I tried that before, but it didn't work out because I had to register in a function's scope, as well as declare stuff in the class scope at the same time.
jameszhao00