Возможно, вам нужны перегрузки функций, параметры по умолчанию, вариативные шаблоны или, возможно, идиома именованных параметров
smoothware
Пожалуйста, обновите выбранный вами ответ до тех, за которые проголосовали, с реальными решениями, а не с высказыванием, получившим мало голосов,No you can't
Альберт Реншоу
Ответы:
158
Вот один из способов сделать это. Он использует список аргументов дважды, сначала для формирования имени вспомогательного макроса, а затем для передачи аргументов этому вспомогательному макросу. Он использует стандартный прием для подсчета количества аргументов макроса.
Это довольно круто, но я не думаю, что сработало бы, если бы я просто сделал PRINT_STRING. В этом случае не было бы распечатки по умолчанию (и это действительно тот случай, который я хочу использовать). Тем не менее +1 за действительно круто.
Cenoc
2
у меня работает в gcc (и это очень умно!) :-), но не работает у меня в Visual Studio :-(
Тим Градуэлл
4
@TimGradwell - это из-за ошибки в компиляторе MSVC, которую они признали, но не исправляли почти десять лет. Тем не менее, обходные доступны .
BeeOnRope
Умно, но не работает для необязательных аргументов макроса с переменным числом аргументов из-за того, что у вас есть «выталкивание» в «GET_4th_ARG».
searchchengine27
это PRINT_STRING_MACRO_CHOOSERвообще нужно? Могу ли я заменить его внутренним телом напрямую и назвать все это с помощью (__VA_ARGS__)?
Херрготт,
85
С большим уважением к Дереку Ледбеттеру за его ответ - и с извинениями за то, что возродил старый вопрос.
Понимание того, что он делает, и изучение способности предшествовать __VA_ARGS__с, ##позволило мне придумать вариант ...
// The multiple macros that you would need anyway [as per: Crazy Eddie]#define XXX_0()<code for no arguments>#define XXX_1(A)<code for one argument>#define XXX_2(A,B)<code for two arguments>#define XXX_3(A,B,C)<code for three arguments>#define XXX_4(A,B,C,D)<code for four arguments>// The interim macro that simply strips the excess and ends up with the required macro#define XXX_X(x,A,B,C,D,FUNC,...) FUNC
// The macro that the programmer uses #define XXX(...) XXX_X(,##__VA_ARGS__,\
XXX_4(__VA_ARGS__),\
XXX_3(__VA_ARGS__),\
XXX_2(__VA_ARGS__),\
XXX_1(__VA_ARGS__),\
XXX_0(__VA_ARGS__)\
)
Для неспециалистов вроде меня, которые наткнулись на ответ, но не совсем понимают, как он работает, я пошагово рассмотрю фактическую обработку, начиная со следующего кода ...
XXX();
XXX(1);
XXX(1,2);
XXX(1,2,3);
XXX(1,2,3,4);
XXX(1,2,3,4,5);// Not actually valid, but included to show the process
Вы можете получить явную ошибку компиляции, если преобразовали выбранный аргумент, который должен быть именем МАКРОСА, в строку, используя # (знак фунта), и сравнили его первые n символов с ожидаемым префиксом и, если совпадения нет, напечатали информативный ошибка.
AturSams 07
1
Вау, не знаю, работает ли это, но, по крайней мере, очень креативно!
Ограниченное искупление
4
почему первый аргумент всегда пуст? почему мы не можем просто его опустить: XXX_X(,##__VA_ARGS__,` ... XXX_X (, XXX_4 (), XXX_3 (), XXX_2 (), XXX_1 (), XXX_0 ()); `
rahman
2
Пустой первый аргумент (запятая) важен. ## __ VA_ARGS__, если перед ним стоит запятая - удаляет запятую, если ## __ VA_ARGS__ заменяется на ничего. Вы можете увидеть это в примере «Становится ...», так как первая строка (без аргументов) имеет только 6 параметров, а остальные получают 7. Этот трюк гарантирует, что ситуация без аргументов работает
Дэвид Сорковский
@Eric - это из-за ошибки в компиляторах Microsoft, но вы можете увидеть этот вопрос для обходных путей.
BeeOnRope
31
Макросы C ++ не изменились по сравнению с C. Поскольку в C не было аргументов перегрузки и аргументов по умолчанию для функций, у него определенно не было их для макросов. Итак, чтобы ответить на ваш вопрос: нет, эти функции не существуют для макросов. Ваш единственный вариант - определить несколько макросов с разными именами (или вообще не использовать макросы).
В качестве примечания: в C ++ обычно считается хорошей практикой максимально отказаться от макросов. Если вам нужны такие функции, есть большая вероятность, что вы злоупотребляете макросами.
Обратите внимание, что причина, по которой невозможно «перегрузить» макросы, заключается в том, что они не имеют присущих им типов. Макросы просто расширяются.
mk12
2
Хотя я использую макросы как можно меньше, я обнаружил , что отладка с помощью вывода трассировки получает совсем немного проще с такими вещами , как __FILE__и __LINE__и такие ...
Условная компиляция и отладка / ведение журнала - это область, в которой макросы действительно удобны и законны. Это знает каждый серьезный программист. Хорошая практика - уйти от использования макросов для определения констант и делать сумасшедшие вещи кодирования уровня C для создания шаблонов контейнеров. Я бы хотел, чтобы C ++ также добавил больше функций в макросы. Они ортогональны шаблонам. Лучшими, конечно, были бы кодлеты, которые позволяют мне добавлять генераторы в компилятор для специфичного для предметной области языка (аспектов).
Lothar
1
Я также думаю, что это не лучший ответ, потому что макрос - это нечто совершенно иное, чем любой вариант языка C ++, потому что он будет обрабатываться ДО компилятора. Таким образом, вы можете делать другие вещи, и ни один компилятор или компоновщик не должен оптимизировать код, потому что, возможно, его не нужно оптимизировать.
alabamajack 03
26
С большим уважением к Дереку Ледбеттеру , Дэвиду Сорковскому , Syphorlate за их ответы, а также за изобретательный метод обнаружения пустых аргументов макроса, разработанный Йенсом Густедтом в
наконец, я придумываю что-то, что включает все уловки, так что
Использует только стандартные макросы C99 для достижения перегрузки функций, без расширения GCC / CLANG / MSVC (т.е. проглатывание запятой в конкретном выражении , ##__VA_ARGS__для GCC / CLANG и неявное проглатывание ##__VA_ARGS__для MSVC). Так что не стесняйтесь передавать недостающее --std=c99вашему компилятору, если хотите =)
Работает как с нулевым аргументом , так и с неограниченным количеством аргументов , если вы расширите его дальше в соответствии с вашими потребностями
Достаточно кроссплатформенный , по крайней мере, протестирован на
GNU / Linux + GCC (GCC 4.9.2 на CentOS 7.0 x86_64)
GNU / Linux + CLANG / LLVM , (CLANG / LLVM 3.5.0 на CentOS 7.0 x86_64)
OS X + Xcode , (XCode 6.1.1 в OS X Yosemite 10.10.1)
Windows + Visual Studio , (Visual Studio 2013 с обновлением 4 для 64-разрядной версии Windows 7 SP1)
Для ленивых просто перейдите к самому последнему посту, чтобы скопировать исходный код. Ниже приводится подробное объяснение, которое, надеюсь, поможет и вдохновит всех людей, ищущих общие __VA_ARGS__решения, таких как я. знак равно
Вот как это происходит. Сначала определит функцию «» перегруженный пользователя видно, я назвал его create, и связанным с этим фактическим определением функции realCreate, и макроопределение с различным числом аргументов CREATE_2, CREATE_1, CREATE_0, как показано ниже:
MACRO_CHOOSER(__VA_ARGS__)Часть в конечном счете решает имена макроопределений, а вторая (__VA_ARGS__)часть содержит списки параметров. Итак, обращение пользователя к create(10)разрешается CREATE_1(10), CREATE_1часть исходит от MACRO_CHOOSER(__VA_ARGS__), а (10)часть - от второй (__VA_ARGS__).
MACRO_CHOOSERИспользует трюк , который, если __VA_ARGS__пусто, то следующее выражение сцепляется в действительный макровызов препроцессор:
NO_ARG_EXPANDER __VA_ARGS__ ()// simply shrinks to NO_ARG_EXPANDER()
Изобретательно, мы можем определить этот результирующий вызов макроса как
#define NO_ARG_EXPANDER(),,CREATE_0
Обратите внимание на две запятые, они скоро будут объяснены. Следующий полезный макрос:
Как следует из названия макроса, мы должны подсчитать количество аргументов позже. А вот еще одна уловка: препроцессор выполняет только простую замену текста. Он выводит количество аргументов макроса просто из количества запятых в круглых скобках. Фактические «аргументы», разделенные запятыми, не обязательно должны иметь допустимый синтаксис. Это может быть любой текст. То есть, в приведенном выше примере NO_ARG_EXPANDER 10 ()считается 1 аргумент для среднего вызова. NO_ARG_EXPANDER 20и 20 ()считаются 2 аргументами для нижнего вызова соответственно.
Если мы используем следующие вспомогательные макросы для их дальнейшего расширения
Завершение ,после CREATE_1- это обходной путь для GCC / CLANG, подавляющий (ложноположительную) ошибку, сообщающую, что ISO C99 requires rest arguments to be usedпри передаче -pedanticвашему компилятору. Это FUNC_RECOMPOSERобходной путь для MSVC, иначе он не может правильно подсчитать количество аргументов (т. Е. Запятых) внутри скобок вызовов макросов. Результаты далее разрешаются к
Как вы, возможно, заметили, последний единственный шаг, который нам нужен, - это использовать стандартный трюк с подсчетом аргументов, чтобы наконец выбрать нужные имена версий макросов:
#define FUNC_CHOOSER(_f1, _f2, _f3,...) _f3
который разрешает результаты
CREATE_0();
CREATE_1(10);
CREATE_2(20,20);
и, безусловно, дает нам желаемые, фактические вызовы функций:
Несмотря на сложность, уродливость, обременяющую разработчика API, для нас, сумасшедших, приходит решение для перегрузки и установки дополнительных параметров функций C / C ++. Использование выходящих перегруженных API становится очень приятным и приятным. знак равно
Если есть возможность дальнейшего упрощения этого подхода, сообщите мне об этом по адресу
@Phylliida ideone.com/jD0Hm5 - поддерживается от нуля до пяти аргументов.
xx
9
Для тех, кто мучительно ищет решение VA_NARGS, которое работает с Visual C ++. Следующий макрос работал у меня безупречно (также с нулевыми параметрами!) В Visual C ++ Express 2010:
#define VA_NUM_ARGS_IMPL(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,N,...) N
#define VA_NUM_ARGS_IMPL_(tuple) VA_NUM_ARGS_IMPL tuple
#define VA_NARGS(...)bool(#__VA_ARGS__)?(VA_NUM_ARGS_IMPL_((__VA_ARGS__,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1))):0
Если вам нужен макрос с необязательными параметрами, вы можете:
Я получаюunresolved external symbol _bool referenced in function _main
Авидан Борисов
да, в некоторых случаях такое может случиться. вам нужно знать, что bool (#__ VA_ARGS__)? отличается от других макросов, поскольку он оценивается во время выполнения. в зависимости от вашего случая вы можете опустить эту часть кода.
Syphorlate
2
На самом деле я остановился на pastebin.com/H3T75dcn, который отлично работает (тоже 0 аргументов).
Авидан Борисов
Спасибо за ссылку, и да, вы также можете сделать это с помощью sizeof, но для меня это не сработало в некоторых случаях, но принцип тот же (логическая оценка).
Syphorlate
Не могли бы вы привести несколько примеров, когда это не удается?
Авидан Борисов
7
gcc/ g++поддерживает макросы varargs, но я не думаю, что это стандарт, поэтому используйте его на свой страх и риск.
Они являются стандартными для C99, и они также добавляются в C ++ 0x.
greyfade
5
#include<stdio.h>#define PP_NARG(...) \
PP_NARG_(__VA_ARGS__,PP_RSEQ_N())#define PP_NARG_(...) \
PP_ARG_N(__VA_ARGS__)#define PP_ARG_N( \
_1, _2, _3, _4, _5, _6, _7, _8, _9,_10, \
_11,_12,_13,_14,_15,_16,_17,_18,_19,_20, \
_21,_22,_23,_24,_25,_26,_27,_28,_29,_30, \
_31,_32,_33,_34,_35,_36,_37,_38,_39,_40, \
_41,_42,_43,_44,_45,_46,_47,_48,_49,_50, \
_51,_52,_53,_54,_55,_56,_57,_58,_59,_60, \
_61,_62,_63,N,...) N
#define PP_RSEQ_N() \
63,62,61,60, \
59,58,57,56,55,54,53,52,51,50, \
49,48,47,46,45,44,43,42,41,40, \
39,38,37,36,35,34,33,32,31,30, \
29,28,27,26,25,24,23,22,21,20, \
19,18,17,16,15,14,13,12,11,10, \
9,8,7,6,5,4,3,2,1,0#define PP_CONCAT(a,b) PP_CONCAT_(a,b)#define PP_CONCAT_(a,b) a ## b#define THINK(...) PP_CONCAT(THINK_, PP_NARG(__VA_ARGS__))(__VA_ARGS__)#define THINK_0() THINK_1("sector zz9 plural z alpha")#define THINK_1(location) THINK_2(location,42)#define THINK_2(location,answer) THINK_3(location, answer,"deep thought")#define THINK_3(location,answer,computer) \
printf ("The answer is %d. This was calculated by %s, and a computer to figure out what this"" actually means will be build in %s\n",(answer),(computer),(location))int
main (int argc,char*argv[]){
THINK ();/* On compilers other than GCC you have to call with least one non-default argument */}
в вашем коде есть ошибка. пожалуйста, сделайте :%s/MY_MACRO_/THINK_/g:)
João Portela
кроме того, он не работал с нулевыми аргументами с использованием g ++i686-apple-darwin10-g++-4.2.1 (GCC) 4.2.1 (Apple Inc. build 5664)
Жоао Портела
1
Для макросов с переменным адресом не существует нулевых аргументов, поскольку пустой токен является допустимым заполнителем.
Пол Фульц II
3
На самом деле препроцессор не для этого предназначен.
Тем не менее, если вы хотите войти в область серьезного программирования макросов с минимальной удобочитаемостью, вам следует взглянуть на библиотеку препроцессора Boost . В конце концов, это не был бы C ++, если бы не было трех полностью совместимых с Тьюрингом уровней программирования (препроцессор, метапрограммирование шаблонов и базовый уровень C ++)!
Как большой поклонник ужасных макромонстров, я хотел расширить ответ Джейсона Дэна и сделать его действительно пригодным для использования. (Хорошо это или плохо.) Оригинал не очень удобен, потому что вам нужно изменять большой алфавитный суп каждый раз, когда вы хотите создать новый макрос, и еще хуже, если вам нужно другое количество аргументов.
Итак, я сделал версию с такими функциями:
0 аргумент case работает
От 1 до 16 аргументов без каких-либо изменений в беспорядочной части
Легко написать больше макросов
Протестировано в gcc 10, clang 9, Visual Studio 2017
В настоящее время я только что сделал максимум 16 аргументов, но если вам нужно больше (правда? Вы просто становитесь глупым ...), вы можете отредактировать FUNC_CHOOSER и CHOOSE_FROM_ARG_COUNT, а затем добавить запятые в NO_ARG_EXPANDER.
Пожалуйста, см. Отличный ответ Джейсона Денга для получения более подробной информации о реализации, но я просто помещу здесь код:
#include<stdio.h>void realCreate(int x,int y){
printf("(%d, %d)\n", x, y);}// This part you put in some library header:#define FUNC_CHOOSER(_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7, _f8, _f9, _f10, _f11, _f12, _f13, _f14, _f15, _f16,...) _f16
#define FUNC_RECOMPOSER(argsWithParentheses) FUNC_CHOOSER argsWithParentheses
#define CHOOSE_FROM_ARG_COUNT(F,...) FUNC_RECOMPOSER((__VA_ARGS__, \
F##_16, F##_15, F##_14, F##_13, F##_12, F##_11, F##_10, F##_9, F##_8,\
F##_7, F##_6, F##_5, F##_4, F##_3, F##_2, F##_1, ))#define NO_ARG_EXPANDER(FUNC),,,,,,,,,,,,,,,,FUNC ## _0#define MACRO_CHOOSER(FUNC,...) CHOOSE_FROM_ARG_COUNT(FUNC, NO_ARG_EXPANDER __VA_ARGS__ (FUNC))#define MULTI_MACRO(FUNC,...) MACRO_CHOOSER(FUNC, __VA_ARGS__)(__VA_ARGS__)// When you need to make a macro with default arguments, use this:#define create(...) MULTI_MACRO(CREATE, __VA_ARGS__)#define CREATE_0() CREATE_1(0)#define CREATE_1(x) CREATE_2(x,0)#define CREATE_2(x, y) \
do{ \
/* put whatever code you want in the last macro */ \
realCreate(x, y); \
}while(0)int main(){
create();
create(10);
create(20,20);//create(30, 30, 30); // Compilation errorreturn0;}
В зависимости от того, что вам нужно, вы можете сделать это с помощью макросов var args . Теперь, необязательных параметров или перегрузки макроса, такого нет.
Ни один из вышеперечисленных примеров (от Дерека Ледбеттера, Дэвида Сорковского и Джо Д.) для подсчета аргументов с помощью макросов не работал у меня с использованием Microsoft VCC 10. __VA_ARGS__Аргумент всегда рассматривается как один аргумент (токенизируя его ##или нет), поэтому сдвиг аргументов, на который опираются эти примеры, не работает.
Итак, короткий ответ, как было сказано многими другими выше: нет, вы не можете перегружать макросы или использовать в них необязательные аргументы.
Можно, но только в C99 или C ++ 11 (из-за наличия __VA_ARGS__). VC2010 - это C89 / C ++ 03 (некоторые биты C ++ 11 начинают появляться, но еще не этот).
No you can't
Ответы:
Вот один из способов сделать это. Он использует список аргументов дважды, сначала для формирования имени вспомогательного макроса, а затем для передачи аргументов этому вспомогательному макросу. Он использует стандартный прием для подсчета количества аргументов макроса.
Это упрощает задачу для вызывающего макроса, но не для писателя.
источник
PRINT_STRING_MACRO_CHOOSER
вообще нужно? Могу ли я заменить его внутренним телом напрямую и назвать все это с помощью(__VA_ARGS__)
?С большим уважением к Дереку Ледбеттеру за его ответ - и с извинениями за то, что возродил старый вопрос.
Понимание того, что он делает, и изучение способности предшествовать
__VA_ARGS__
с,##
позволило мне придумать вариант ...Для неспециалистов вроде меня, которые наткнулись на ответ, но не совсем понимают, как он работает, я пошагово рассмотрю фактическую обработку, начиная со следующего кода ...
Становится ...
Что становится лишь шестым аргументом ...
PS: Удалите #define для XXX_0, чтобы получить ошибку компиляции [то есть: если опция без аргументов не разрешена].
PPS: Было бы неплохо, если бы недопустимые ситуации (например: 5) были чем-то, что давало бы программисту более четкую ошибку компиляции!
PPPS: Я не эксперт, поэтому очень рад слышать комментарии (хорошие, плохие и другие)!
источник
XXX_X(,##__VA_ARGS__,` ...
XXX_X (, XXX_4 (), XXX_3 (), XXX_2 (), XXX_1 (), XXX_0 ()); `Макросы C ++ не изменились по сравнению с C. Поскольку в C не было аргументов перегрузки и аргументов по умолчанию для функций, у него определенно не было их для макросов. Итак, чтобы ответить на ваш вопрос: нет, эти функции не существуют для макросов. Ваш единственный вариант - определить несколько макросов с разными именами (или вообще не использовать макросы).
В качестве примечания: в C ++ обычно считается хорошей практикой максимально отказаться от макросов. Если вам нужны такие функции, есть большая вероятность, что вы злоупотребляете макросами.
источник
__FILE__
и__LINE__
и такие ...С большим уважением к Дереку Ледбеттеру , Дэвиду Сорковскому , Syphorlate за их ответы, а также за изобретательный метод обнаружения пустых аргументов макроса, разработанный Йенсом Густедтом в
https://gustedt.wordpress.com/2010/06/08/detect-empty-macro-arguments/
наконец, я придумываю что-то, что включает все уловки, так что
, ##__VA_ARGS__
для GCC / CLANG и неявное проглатывание##__VA_ARGS__
для MSVC). Так что не стесняйтесь передавать недостающее--std=c99
вашему компилятору, если хотите =)Достаточно кроссплатформенный , по крайней мере, протестирован на
Для ленивых просто перейдите к самому последнему посту, чтобы скопировать исходный код. Ниже приводится подробное объяснение, которое, надеюсь, поможет и вдохновит всех людей, ищущих общие
__VA_ARGS__
решения, таких как я. знак равноВот как это происходит. Сначала определит функцию «» перегруженный пользователя видно, я назвал его
create
, и связанным с этим фактическим определением функцииrealCreate
, и макроопределение с различным числом аргументовCREATE_2
,CREATE_1
,CREATE_0
, как показано ниже:MACRO_CHOOSER(__VA_ARGS__)
Часть в конечном счете решает имена макроопределений, а вторая(__VA_ARGS__)
часть содержит списки параметров. Итак, обращение пользователя кcreate(10)
разрешаетсяCREATE_1(10)
,CREATE_1
часть исходит отMACRO_CHOOSER(__VA_ARGS__)
, а(10)
часть - от второй(__VA_ARGS__)
.MACRO_CHOOSER
Использует трюк , который, если__VA_ARGS__
пусто, то следующее выражение сцепляется в действительный макровызов препроцессор:Изобретательно, мы можем определить этот результирующий вызов макроса как
Обратите внимание на две запятые, они скоро будут объяснены. Следующий полезный макрос:
так что звонки
фактически расширены до
Как следует из названия макроса, мы должны подсчитать количество аргументов позже. А вот еще одна уловка: препроцессор выполняет только простую замену текста. Он выводит количество аргументов макроса просто из количества запятых в круглых скобках. Фактические «аргументы», разделенные запятыми, не обязательно должны иметь допустимый синтаксис. Это может быть любой текст. То есть, в приведенном выше примере
NO_ARG_EXPANDER 10 ()
считается 1 аргумент для среднего вызова.NO_ARG_EXPANDER 20
и20 ()
считаются 2 аргументами для нижнего вызова соответственно.Если мы используем следующие вспомогательные макросы для их дальнейшего расширения
Завершение
,
послеCREATE_1
- это обходной путь для GCC / CLANG, подавляющий (ложноположительную) ошибку, сообщающую, чтоISO C99 requires rest arguments to be used
при передаче-pedantic
вашему компилятору. ЭтоFUNC_RECOMPOSER
обходной путь для MSVC, иначе он не может правильно подсчитать количество аргументов (т. Е. Запятых) внутри скобок вызовов макросов. Результаты далее разрешаются кКак вы, возможно, заметили, последний единственный шаг, который нам нужен, - это использовать стандартный трюк с подсчетом аргументов, чтобы наконец выбрать нужные имена версий макросов:
который разрешает результаты
и, безусловно, дает нам желаемые, фактические вызовы функций:
Собрав все вместе, с некоторой перестановкой операторов для лучшей читаемости, весь исходный код примера с двумя аргументами находится здесь:
Несмотря на сложность, уродливость, обременяющую разработчика API, для нас, сумасшедших, приходит решение для перегрузки и установки дополнительных параметров функций C / C ++. Использование выходящих перегруженных API становится очень приятным и приятным. знак равно
Если есть возможность дальнейшего упрощения этого подхода, сообщите мне об этом по адресу
https://github.com/jason-deng/C99FunctionOverload
Еще раз выражаю особую благодарность всем блестящим людям, которые вдохновили меня на эту работу! знак равно
источник
Для тех, кто мучительно ищет решение VA_NARGS, которое работает с Visual C ++. Следующий макрос работал у меня безупречно (также с нулевыми параметрами!) В Visual C ++ Express 2010:
Если вам нужен макрос с необязательными параметрами, вы можете:
Это сработало для меня, как и в vc. Но для нулевых параметров это не работает.
источник
unresolved external symbol _bool referenced in function _main
gcc
/g++
поддерживает макросы varargs, но я не думаю, что это стандарт, поэтому используйте его на свой страх и риск.источник
ОТКАЗ ОТ ОТВЕТСТВЕННОСТИ: В основном безвредны.
источник
:%s/MY_MACRO_/THINK_/g
:)i686-apple-darwin10-g++-4.2.1 (GCC) 4.2.1 (Apple Inc. build 5664)
На самом деле препроцессор не для этого предназначен.
Тем не менее, если вы хотите войти в область серьезного программирования макросов с минимальной удобочитаемостью, вам следует взглянуть на библиотеку препроцессора Boost . В конце концов, это не был бы C ++, если бы не было трех полностью совместимых с Тьюрингом уровней программирования (препроцессор, метапрограммирование шаблонов и базовый уровень C ++)!
источник
В момент вызова вы знаете, сколько аргументов вы собираетесь передать, поэтому нет необходимости в перегрузке.
источник
Более сжатая версия кода Дерека Ледбеттера:
источник
Как большой поклонник ужасных макромонстров, я хотел расширить ответ Джейсона Дэна и сделать его действительно пригодным для использования. (Хорошо это или плохо.) Оригинал не очень удобен, потому что вам нужно изменять большой алфавитный суп каждый раз, когда вы хотите создать новый макрос, и еще хуже, если вам нужно другое количество аргументов.
Итак, я сделал версию с такими функциями:
В настоящее время я только что сделал максимум 16 аргументов, но если вам нужно больше (правда? Вы просто становитесь глупым ...), вы можете отредактировать FUNC_CHOOSER и CHOOSE_FROM_ARG_COUNT, а затем добавить запятые в NO_ARG_EXPANDER.
Пожалуйста, см. Отличный ответ Джейсона Денга для получения более подробной информации о реализации, но я просто помещу здесь код:
источник
Вы можете использовать
BOOST_PP_OVERLOAD
изboost
библиотеки.Пример из официального документа по ускорению :
источник
В зависимости от того, что вам нужно, вы можете сделать это с помощью макросов var args . Теперь, необязательных параметров или перегрузки макроса, такого нет.
источник
Ни один из вышеперечисленных примеров (от Дерека Ледбеттера, Дэвида Сорковского и Джо Д.) для подсчета аргументов с помощью макросов не работал у меня с использованием Microsoft VCC 10.
__VA_ARGS__
Аргумент всегда рассматривается как один аргумент (токенизируя его##
или нет), поэтому сдвиг аргументов, на который опираются эти примеры, не работает.Итак, короткий ответ, как было сказано многими другими выше: нет, вы не можете перегружать макросы или использовать в них необязательные аргументы.
источник