Расширение макроса C / C ++

У меня есть следующий код:

#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;\
}

Когда я вызываю макрос с

UNIT_IMPLEMENT_UNIT_TYPE(DISTANCE, METER)

Я получаю ошибки компиляции:

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'

это означает, что макрос не был раскрыт так, как я хотел, в последней строке внутри скобок.
Что я сделал не так?

3

Решение

#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)

Удалите пробелы между именем макроса и списком аргументов. Это должно быть:

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

Когда есть место, как это:

#define FOO (params) replacement

это определяет объектоподобный макрос, где символ заменяется непосредственно списком замены без подстановки параметров. Итак, такой вызов:

FOO(bar)

расширяется до этого:

(params) replacement

Убрав пробел, вы получите функциональный макрос как предполагалось:

#define FOO(params) replacement

а также FOO(bar) правильно расширяется до replacement,

6

Другие решения


По вопросам рекламы [email protected]