Комментарии 26
А где здесь макросы, вы показали типичный метод с переменным числом параметров. В данном случае виден типичный обман :-)
Вообще от этого давно пора уходить на потоки.
Вообще от этого давно пора уходить на потоки.
Само собой в некотором смысле это обман, ведь макросов с переменным количеством аргументов не бывает.
Макрос тут:
Используется так:
dbg (...) будет развернуто в вызов
из которого видно, что сначала вызывается функция DbgFuncRet, возвращающая указатель на другую функцию, к которой и применяются вторые скобки.
Причем здесь потоки я не понял.
Макрос тут:
// Собственно сам макрос
#define dbg DbgFuncRet(__FILE__, __LINE__)
Используется так:
int main ()
{
// ....
dbg ("Test %d, %s, %f\n", 100, "test-test", 99.99f);
}
dbg (...) будет развернуто в вызов
DbgFuncRet(__FILE__, __LINE__)("Test %d, %s, %f\n", 100, "test-test", 99.99f);
из которого видно, что сначала вызывается функция DbgFuncRet, возвращающая указатель на другую функцию, к которой и применяются вторые скобки.
Причем здесь потоки я не понял.
Ну я это и имел ввиду, что макрос на самом деле не принимает параметры, а заворачивает метод, который в свою очередь возвращает функтор, я у себя же так делать не стал, ибо это довольно жуткий и устаревший подход. Я у себя использовал потоки и boost::format, который является безопасным, решения было принято для возможности локализации логов и соответственно нормальной обработки косяков в случае недобора или перебора параметров.
Макросы с переменным числом параметров бывают. Я-то грешным делом подумал, что статья именно об этой методике.
Пример из написанной мной библиотеки Logger для журналирования в Qt-приложениях:
Используется это примерно так:
Собственно, использования Variadic Macros описано в статье в англоязычной Википедии :)
Пример из написанной мной библиотеки Logger для журналирования в Qt-приложениях:
#define LOG_DEBUG(...) Logger::write(Logger::Debug, __FILE__, __LINE__, Q_FUNC_INFO, ##__VA_ARGS__)
...
class Logger
{
...
static void write(LogLevel logLevel, const char* file, int line, const char* function, const char* message);
static QDebug write(LogLevel logLevel, const char* file, int line, const char* function);
...
}
Используется это примерно так:
LOG_DEBUG("Message 1");
LOG_DEBUG() << "Message 2" << "ok";
Собственно, использования Variadic Macros описано в статье в англоязычной Википедии :)
>ведь макросов с переменным количеством аргументов не бывает.
добавлены в С с 99 года, в С++ с 2011
ru.wikipedia.org/wiki/Вариативный_макрос
добавлены в С с 99 года, в С++ с 2011
ru.wikipedia.org/wiki/Вариативный_макрос
Как это макросов с переменным числом аргументов не бывает?
#if defined(__GNUC__) || defined(__GCCE__)
#define DLOG(x, args...) (isNiocoreLogEnabled? DOutDebugMessage(x, args): ((void)0))
#else
#define DLOG(x, ...) (isNiocoreLogEnabled? DOutDebugMessage(x, __VA_ARGS__): ((void)0))
#endif
Добавьте развернутый пример использования, чтобы у людей меньше вопросов было.
что-то я не понял, зачем так делать, если, например, в gcc есть все нужное:
А еще можно даже без gettext'а на макросах сделать «велосипедную» псевдолокализацию:
И вообще, конечно, макросы — штука занятная.
// debug mode, -DEBUG
#ifdef EBUG
#define RED "\033[1;32;41m"
#define GREEN "\033[5;30;42m"
#define OLDCOLOR "\033[0;0;0m"
#define FNAME() fprintf(stderr, "\n%s (%s, line %d)\n", __func__, __FILE__, __LINE__)
#define DBG(...) do{fprintf(stderr, "%s (%s, line %d): ", __func__, __FILE__, __LINE__); \
fprintf(stderr, __VA_ARGS__); \
fprintf(stderr, "\n");} while(0)
#else
#define FNAME() do{}while(0)
#define DBG(...) do{}while(0)
#endif //EBUG
А еще можно даже без gettext'а на макросах сделать «велосипедную» псевдолокализацию:
// locale.h
#define _LANG(_var, _ru, _en) char _var##ru[] = _ru;\
char _var##en[] = _en;\
char *_var[2] = {_var##ru, _var##en};
#define _L(x) (x[Lang])
unsigned char Lang = 1; // по умолчанию - английский, меняем на русский, если LC_MESSAGES==ru или HTTP_ACCEPT_LANGUAGE==ru
_LANG(_s_Name_, "Ваше имя", "Your name");
…
// file.c
printf("%s:<input ... >\n", _L(_s_Name_));
И вообще, конечно, макросы — штука занятная.
а нужно было написать всего 3 строки:
#define QUOTE_(WHAT) #WHAT
#define QUOTE(WHAT) QUOTE_(WHAT)
#define dbg(format, ...) printf("%s: "format, __FILE__":"QUOTE(__LINE__), ## __VA_ARGS__)
Вот всегда так на Хабре — мучаешься, думаешь, пишешь 2 дня статью, а оказывается что всё можно сделать в 3 строки. Автору — обидно, читателю — профит.
Спасибо.
Спасибо.
Ну, любому автору, перед тем как писать статью на хабр (да и не только) о новоизобретенном велосипеде, имеет смысл чутка погуглить, не переоткрывает ли он Америку. В частности, если собираешься писать о «расширении» функционала языка, стоит серьезно поисследовать, точно ли такого функционала нет в наличии по умолчанию :-)
Там же описан костыль для говнокомпилятора
Давно не использовал С, подскажите, зачем два макроса QUOTE() и QUOTE_(), почему нельзя одним обойтись?
опять любители комментировать, а не читать. там же прямо написано «нашел такое решение, но у меня VC6». Да и упоминавшийся StdAfx.h мог бы навести на мысли…
А переменное число параметров чистым препроцессором можно сделать так:
вся штука в том, что вызывать это нужно будет так:
то есть, по две пары скобок писать
А переменное число параметров чистым препроцессором можно сделать так:
#define dbg(X) do { printf X; printf("File: %s:%s\n" __FILE__, __LINE__); } while(0)
вся штука в том, что вызывать это нужно будет так:
dbg(("debugging is %s", debug? "on" : "off"))
то есть, по две пары скобок писать
И вообще почему VS6? Это какое-то принципиальное требование?
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
Макросы с переменным числом параметров