2014-09-04 3 views
3

Я следующий код: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' 

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

+1

'UNIT_BASIC_ ## name' ->' UNIT_BASIC _ ## name'? – someuser

+1

Какой компилятор вы используете? GCC работает отлично, по крайней мере дает разные ошибки: http://coliru.stacked-crooked.com/a/06956e449b44eee3 –

+0

Я использую g ++ (дважды проверено: это GCC) и меняется на это: #define UNIT_BASIC_UNIT_DEF2 (имя) UNIT_BASIC _ ## имя #define UNIT_UNIT_TYPE_DEF2 (basic_type, имя) АГРЕГАТ _ ## basic_type ## _ ## имя #define UNIT_BASIC_UNIT_CLASS_NAME2 (имя) Кунит ## имя #define UNIT_UNIT_TYPE_CLASS_NAME2 (basic_type, имя) Кунит ## basic_type ## _ ## name не помогло. Такая же ошибка. –

ответ

6
#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.

+0

Вы правы! Это сделал трюк! –

Смежные вопросы