Скажем, у меня есть макрос:
#define SUBST(MAGIC, ...) __VA_ARGS__ /* this won't work*/
И я хочу назвать это так:
SUBST(int, MAGIC a = 1);
// expected output:
int a = 1;
Есть ли какой-то набор диких косвенных обращений и расширений, которые я могу использовать для принудительного расширения MAGIC во втором аргументе со значением, которое зависит от вызова макроса?
Это происходит, когда другие аргументы поступают из другого слоя, а макрос SUBST повторяется много раз с разными значениями MAGIC.
Например:
#define WRAP(function, MAGIC, stuff, ...) \
void function(__VA_ARGS__) { stuff };
#define SUPERWRAP(function, stuff, ...) \
WRAP(function, uint8_t, stuff##_u8, __VA_ARGS__) \
WRAP(function, uint16_t, stuff##_u16, __VA_ARGS__)
SUPERWRAP(example, EXAMPLE_IMPL, template_t<MAGIC>, int)
Что не может быть решено в шаблонах, потому что:
#define WRAP(function, stuff, ...) \
template<class MAGIC>
int function(__VA_ARGS__) { stuff }
WRAP(example, /*...*/, template_t<MAGIC>, int)
не допускает специализированной реализации, и использование типа в качестве аргумента шаблона в специализации является частичной специализацией, которая также является незаконной.
Пожалуйста, добавьте пример, содержащий несколько различных желаемых примеров использования. Возможно, есть способ сделать это вообще без использования макросов. Пожалуйста, добавьте несколько из них к вопросу. (Должно быть как минимум 2 разных значения для первого аргумента макроса и несколько для 2, и всего более одного, чем 2 аргумента.)
В исходном вопросе не было template, и он был макровопросом. Но теперь это больше похоже на вопрос C++. Должны ли вы настроить теги, чтобы отразить это?
Я не понимаю пример, просто WRAP(example, uint8_t, /*...*/, template_t<uint8_t>, int). Или #define WRAP2(a, b, c, ...) WRAP(a, b, c, template_t<b>, __VA_ARGS__)
@KamilCuk Я добавил еще один слой макроса, чтобы продемонстрировать, как __VA_ARGS__ многократно используется с разными типами (на практике в гораздо большем комбинаторном масштабе, но я думаю, что это иллюстрирует проблему).
На самом деле я разработал решение для особого случая для этой проблемы, и может быть возможно создать новый вид специального случая для примера, который я привел, но я не хочу повторять всю эту сложность. снова и надеялся на что-то более общее.
@CraigEstey Изначально я сделал «простой пример» слишком простым, и мне было предложено удалить тег C++. Затем меня попросили привести более полный пример, и я чувствовал себя неловко, добавляя тег обратно. Но я предполагаю, что на данном этапе это вопрос C++.
#define SUPERWRAP(function, stuff, ...) WRAP(function, uint8_t, stuff##_u8, template_t<uint8_t>, __VA_ARGS__). Это препроцессор - вы должны напечатать его. Если вам нужна строковая замена аргументов функции - это вне препроцессора C.





Можно ли заменить слово, используемое в аргументе, на макрос препроцессора?
Нет, невозможно заменить слово, используемое в аргументе, на макрос препроцессора.
SUBST(int, MAGIC a = 1); // expected output: int a = 1;
Это невозможно.
Есть ли какой-то набор диких косвенных обращений и расширений, которые я могу использовать для принудительного расширения MAGIC во втором аргументе со значением, которое зависит от вызова макроса?
Нет.
Например: #define WRAP(функция, MAGIC, материал, ...) \
Использование макросов C для генерации определения функции приводит к сложному для чтения, сопровождения и отладки коду, который никто никогда не сможет исправить или сделать с ним что-либо позже. Подумайте о том, чтобы написать то, что вы хотите, построчно.
Вы можете рассмотреть возможность использования лучшего препроцессора, такого как jinja2, m4 или php.
Ни один из них не является жизнеспособным, когда я должен взаимодействовать с чужим кодом. Десятки тысяч строк копирования-вставки могут быть явными, но поддерживать их — жалкая работа.
На самом деле, мой предыдущий комментарий не отражает истинного ужаса ситуации. Это не просто «чужой код», а интерфейс между чьим-то еще кодом и другим чьим-то кодом. Если бы это был только один кто-то другой, я бы просто поступил по-своему и пошел дальше.
Я хочу сказать, что макросы C великолепны, но становятся неуправляемыми. Рассмотрим что-нибудь еще для генерации кода. Если становится сложно, значит, плохо.
Если бы только я владел системой сборки! У меня есть гибридное решение препроцессора/шаблона, но я нахожу его отвратительным. Я пытался минимизировать препроцессор и сделать что-то более надежное с помощью шаблонов, но шаблоны по-прежнему нуждаются в слишком большой помощи препроцессора.
Единственный способ, которым я вижу, что макрос
SUBSTоценивает то, что вы хотите, — это использовать#define SUBST(MAGIC_PARAM, ...) using MAGIC = MAGIC_PARAM; __VA_ARGS__, но во многих контекстах это просто не сработает. Почему именно вы хотите использовать макрос здесь???