Как удалить избыточный параметр макроса

Некоторое время назад я написал набор X-макросов для грандиозный проект. Мне нужно было поддерживать согласованные списки как строк, так и перечисляемых ссылок / хеш-значений / функций обратного вызова и т. Д. Вот как выглядит обратный вызов функции

#define LREF_LOOKUP_TABLE_TEXT_SIZE 32
#define _LREF_ENUM_LIST(_prefix,_ref,...) _prefix ## _ ## _ref,
#define _LREF_BASE_STRUCT_ENTRY(_prefix,_ref) .text= #_ref "\0", .position= _LREF_ENUM_LIST(_prefix, _ref)
#define _LREF_FUNCTION_STRUCT_LIST(_prefix,_ref,...) {_LREF_BASE_STRUCT_ENTRY(_prefix,_ref) _prefix ## _ ## _ref ## _callback},

#define _LREF_ENUM_TYPEDEF(_prefix)                                               \ 
    typedef enum _prefix                                                          \  
    {                                                                             \  
        _ ## _prefix ## s(_prefix,_LREF_ENUM_LIST)                                \ 
        _LREF_ENUM_LIST(_prefix,tblEnd)                                           \ 
    } e_ ## _prefix

#define _LREF_LOOKUP_TABLE_TYPEDEF(_prefix, _extras)                              \ 
    typedef struct _prefix ## _lookup                                             \ 
    {                                                                             \ 
        const char text[LREF_LOOKUP_TABLE_TEXT_SIZE];                             \ 
        e_ ## _prefix position;                                                   \ 
        _extras                                                                   \ 
    } _prefix ##_lookup_t

#define LREF_GENERIC_LOOKUP_TABLE(_prefix, _type, _tabledef, _listdef, _extras)   \ 
    _LREF_ENUM_TYPEDEF(_prefix);                                                  \ 
    _LREF_LOOKUP_TABLE_TYPEDEF(_prefix,_tabledef);                                \ 
    _extras                                                                       \ 
    _LREF_LOOKUP_TABLE_DECLARATION(_prefix,_listdef, _type)

#define LREF_FUNCTION_LOOKUP_TABLE(_prefix, _type)                                \ 
    _ ## _prefix ## s(_prefix, _LREF_FUNCTION_DEF )                               \ 
    LREF_GENERIC_LOOKUP_TABLE(    _prefix,                                        \ 
        _type,                                                                    \ 
        void* (*function) (void*);,                                               \ 
    _LREF_FUNCTION_STRUCT_LIST,  )

Он находится в файле заголовка и позволяет мне писать такие вещи, как:

#define _cl_tags(x,_)         \
    _(x, command_list)        \
    _(x, command)             \
    _(x, parameter)           \
    _(x, fixed_parameter)     \
    _(x, parameter_group)     \
    _(x, group)               \ 
    _(x, map)                 \
    _(x, transform)

LREF_FUNCTION_LOOKUP_TABLE(cl_tag, static);

Это сокращает процедуры обработки. Например, загрузить файл конфигурации с указанными выше тегами просто:

for (node_tag = cl_tag_lookup_table; node_tag->position != cl_tag_tblEnd; node_tag++)
{
    if (strcasecmp(test_string, node_tag->text) == 0)
    {
        func_return = node_tag->function((void*)m_parser);
    }
}

У меня такой вопрос: мне не нравится, что мне приходится включать второй параметр в мой #define . Я хочу иметь возможность писать #define _cl_tags (_) вместо #define _cl_tags (x, _) . Как видите, x используется только для передачи префикса (cl_tag) вниз. Но это излишне, поскольку префикс является параметром начального макроса.

Решение этой проблемы было бы простым, если бы мой препроцессор сначала расширил бы самые внешние макросы. К сожалению, препроцессор GCC работает через самые внутренние макросы, то есть значения параметров, перед расширением самого внешнего макроса.

Я использую gcc 4.4.5


Пояснение По стандарту C89 (и C99) следующие определения

#define plus(x,y) add(y,x)
#define add(x,y) ((x)+(y))

с вызовом

plus(plus(a,b),c)

должны давать

  1. плюс (plus (a, b), c)
  2. add (c, plus (a, b))
  3. ((c) + (плюс (a, b))
  4. ((c) + (add (b, a))
  5. ((c) + (((b) + (a)) ))

gcc 4.4.5 дает

  1. плюс (плюс (a, b), c)
  2. плюс (добавить (b, a), c)
  3. плюс (((b) + (a )), c)
  4. add (c, ((b) + (a)))
  5. ((c) + ((((b) + (a))))

6
задан Brian Tompsett - 汤莱恩 9 March 2016 в 21:57
поделиться