3

I have the following code:

#define UNIT_BASIC_UNIT_DEF2 (name) UNIT_BASIC_ ## name
#define UNIT_UNIT_TYPE_DEF2 (basic_type, name) UNIT_ ## basic_type ## _ ## name
#define UNIT_BASIC_UNIT_CLASS_NAME2(name) CUnit ## name
#define UNIT_UNIT_TYPE_CLASS_NAME2(basic_type, name) CUnit ## basic_type ## _ ## name

#define UNIT_BASIC_UNIT_DEF (name) UNIT_BASIC_UNIT_DEF2(name)
#define UNIT_UNIT_TYPE_DEF (basic_type, name) UNIT_UNIT_TYPE_DEF2 (basic_type, name)
#define UNIT_BASIC_UNIT_CLASS_NAME(name) UNIT_BASIC_UNIT_CLASS_NAME2(name)
#define UNIT_UNIT_TYPE_CLASS_NAME(basic_type, name) UNIT_UNIT_TYPE_CLASS_NAME2(basic_type, name)

#define UNIT_IMPLEMENT_UNIT_TYPE(basic_type, name) \
CUnitAbstract& UNIT_UNIT_TYPE_CLASS_NAME(basic_type, name)::dup(){\
UNIT_UNIT_TYPE_CLASS_NAME(basic_type, name) * n = new UNIT_UNIT_TYPE_CLASS_NAME(basic_type, name)(this->value);\
return *n;\
}\
CUnitAbstract& UNIT_UNIT_TYPE_CLASS_NAME(basic_type, name) ::operator+(CUnitAbstract& value){\
DYNAMIC_ASSERT(dynamic_cast< UNIT_BASIC_UNIT_CLASS_NAME(basic_type) *>(&value) != NULL);\
CUnitAbstract * tmp = &this->dup();\
*tmp = this->value + conversionTable[UNIT_BASIC_UNIT_DEF(basic_type)][UNIT_UNIT_TYPE_DEF(basic_type, name)] * value.getInBasicUnit();return *tmp;\
}

When I'm calling the macro with

UNIT_IMPLEMENT_UNIT_TYPE(DISTANCE, METER)

I get compilation errors:

error: 'basic_type' was not declared in this scope
error: 'name' was not declared in this scope
error: expected ']' before 'UNIT_basic_type_name'
error: expected ';' before 'UNIT_basic_type_name'

meaning that the macro wasn't expanded as I wanted it to in the last line inside the brackets. What did I do wrong?

G. Ko
  • 403
  • 6
  • 15
  • 1
    `UNIT_BASIC_ ## name` -> `UNIT_BASIC_##name`? – someuser Sep 04 '14 at 06:34
  • 1
    What compiler are you using? GCC works fine, at least gives different errors: http://coliru.stacked-crooked.com/a/06956e449b44eee3 – Anton Savin Sep 04 '14 at 06:36
  • I'm using g++ (double checked: it's GCC) and changing to this: #define UNIT_BASIC_UNIT_DEF2 (name) UNIT_BASIC_##name #define UNIT_UNIT_TYPE_DEF2 (basic_type, name) UNIT_##basic_type##_##name #define UNIT_BASIC_UNIT_CLASS_NAME2(name) CUnit##name #define UNIT_UNIT_TYPE_CLASS_NAME2(basic_type, name) CUnit##basic_type##_##name didn't help. Same error. – G. Ko Sep 04 '14 at 06:45
  • @AntonSavin the error does appear in your link after the following line: main.cpp:6:30: error: ‘name’ was not declared in this scope – G. Ko Sep 04 '14 at 07:05

1 Answers1

7
#define UNIT_BASIC_UNIT_DEF2 (name) UNIT_BASIC_ ## name
#define UNIT_UNIT_TYPE_DEF2 (basic_type, name) UNIT_ ## basic_type ## _ ## name
...
#define UNIT_BASIC_UNIT_DEF (name) UNIT_BASIC_UNIT_DEF2(name)
#define UNIT_UNIT_TYPE_DEF (basic_type, name) UNIT_UNIT_TYPE_DEF2 (basic_type, name)

Remove the spaces between the macro name and the argument list. These should be:

#define UNIT_BASIC_UNIT_DEF2(name) ...
//                         ^^^
//                     no space here!

When there's a space like this:

#define FOO (params) replacement

that defines an object-like macro, where the symbol gets directly replaced by the replacement list, with no parameter substitution. So an invocation like this:

FOO(bar)

gets expanded to this:

(params) replacement

By removing the space, you get a function-like macro as intended:

#define FOO(params) replacement

and FOO(bar) gets correctly expanded to replacement.

Adam Rosenfield
  • 390,455
  • 97
  • 512
  • 589