Почему этот макрос не расширяется? - PullRequest
1 голос
/ 02 апреля 2020

Это вывод препроцессора для assets.cpp.i:

#define CLASSNAME GAMEOBJECT
#define CLASSNAME_NORMAL GameObject
#define GAMEOBJECT_EXPANSION(FUNC) FUNC(std::vector<std::shared_ptr<Component>>, comps)




# 1 "/home/rubend/p/engine/libs/include/prefab.h" 1

#define prefab_h 



#define PREFAB_VAR_ENUM_NAME(name) name ##_enum
#define PREFAB_VAR_ENUM_DIRTY(type,name) PREFAB_VAR_ENUM_NAME(name),


# 42 "/home/rubend/p/engine/libs/include/prefab.h"
#define _CLASSNAME_EXPANSION(classname,func) classname ## _EXPANSION(func)
#define CLASSNAME_EXPANSION(func) _CLASSNAME_EXPANSION(CLASSNAME,func)

template<class T>
class Prefab:public File{
private:
 std::shared_ptr<T> ref;

protected:

 enum DIRTY_ENUM{First, CLASSNAME_EXPANSION(PREFAB_VAR_ENUM_DIRTY) Last};

};

Теперь, почему CLASSNAME_EXPANSION(PREFAB_VAR_ENUM_DIRTY) вообще не расширяется?

Есть ли что-то особенное в токене конкатенации ## I не знаете о?

Я использую G CC 9.3 и CMake 3.16.5

Ответ

Исправлено добавлением еще одного макрос:

#define __CLASSNAME_EXPANSION(classname, func) classname ## _EXPANSION(func)
#define _CLASSNAME_EXPANSION(classname, func) __CLASSNAME_EXPANSION(classname,func)
#define CLASSNAME_EXPANSION(func) _CLASSNAME_EXPANSION(CLASSNAME,func)

Обновление 12/4/20

@ rici указал, что я должен поставить подчеркивание в конце, потому что макросы внутренней библиотеки используют их в начале .

1 Ответ

3 голосов
/ 03 апреля 2020

Если вы последуете за расширением, вы заметите, что CLASSNAME_EXPANSION расширяется - до самого себя.

Давайте шаг за шагом рассмотрим, что происходит:

CLASSNAME_EXPANSION(PREFAB_VAR_ENUM_DIRTY)
-> _CLASSNAME_EXPANSION(CLASSNAME,PREFAB_VAR_ENUM_DIRTY)
-> CLASSNAME ## _EXPANSION(PREFAB_VAR_ENUM_DIRTY)
-> CLASSNAME_EXPANSION(PREFAB_VAR_ENUM_DIRTY)

И так как имя этого макроса совпадает с исходным (то есть это вложенное имя), мы не расширяем его.

...