C ++ Макро текстовые манипуляции - PullRequest
4 голосов
/ 28 января 2011

Я хотел бы написать макрос C ++, принимающий произвольный аргумент, такой как:

#define MANIP(...) \ 
//Implementation

Такой, что запись

MANIP(m_a, m_b, m_c);

расширяется до

f(a, b, c);
g("a", "b", "c");

Этовозможный?

Заранее спасибо за помощь в решении этого, казалось бы, экстравагантного вопроса:)

Ответы [ 4 ]

6 голосов
/ 28 января 2011

Я не верю, что будет простой способ перейти от m_a к a. Однако оператор stringize # является частью стандартных C и C ++.

например, учитывая

#define STRING(x) #x

, тогда STRING(m_a) будет преобразовано в "m_a".

0 голосов
/ 31 января 2011

Препроцессор не может разделять токены. Это означает, что невозможно произвести foo из m_foo или (как недавно было сказано) foo из "foo".

Если вы можете использовать переменные макросы (как указывает Мэтью М., это означает C99 или C ++ 0x), здесь будет полезна библиотека P99 Дженса Гастта. Существуют макросы, которые делают это еще проще, но давайте сделаем это удобочитаемым для людей, которые не знакомы с библиотекой, хорошо?

Упрощенный случай: передано два или три аргумента.

#define MANIP2(a, b) \
    f(a, b)          \
    g(#a, #b)

#define MANIP3(a, b, c) \
    f(a, b, c)          \
    g(#a, #b, #c)

#define MANIP(...)   \
    MANIP_(          \
        P99_PASTE2(MANIP, P99_NARG(__VA_ARGS__)), \
        __VA_ARGS__) \

#define MANIP_(MANIPMAC, ...) MANIPMAC(__VA_ARGS__)

Это иллюстрирует основной принцип. На практике есть макросы в стиле foreach (аналог Boost), которые упрощают кодирование (хотя, как я уже говорил, труднее читать для непосвященных). Подробнее см. Документацию библиотеки P99 .

0 голосов
/ 28 января 2011

Невозможно, чтобы препроцессор (который обрабатывает операторы #define, а не сам компилятор C ++) разбивал аргументы на части. Поэтому, если вы пытаетесь извлечь a из m_a , вы не сможете этого сделать. Вместо этого было бы лучше определить ваш макрос как:

  #define MANIP(m, a, b, c)

И требовать, чтобы 'm' был отдельным входом.

Во-вторых, вы не можете легко конвертировать из нестроковых входных данных в строковые. IE, преобразование из a в "a" не легко выполнимо. Я формулирую это так, поскольку знаю, что некоторые CPP (C-Pre-процессор) могут это сделать. Но я не думаю, что он портативный.

Обычно, когда вы пытаетесь делать сложные вещи, вы должны работать с языком программирования , а не , а не с CPP.

В частности, в C ++ у вас есть шаблоны, которые позволят вам продвинуться намного дальше с такой работой, чем #define для CPP операторов.

0 голосов
/ 28 января 2011
...