Макросы - это, в основном, плохой выбор в C ++, в основном из-за того, что они имеют независимость от пространства имен c и могут вступать в силу там, где это неожиданно.
Тем не менее, пример того, как можно решить проблему OP, например используя вставку токена :
#include <iostream>
#define LOG(LEVEL, ...) LOG_##LEVEL(__VA_ARGS__)
#define LOG_INFO(...) log(Info, __VA_ARGS__)
#define LOG_WARN(...) log(Warn, __VA_ARGS__)
#define LOG_FATAL(...) do { log(Error, __VA_ARGS__); std::cerr << "Program aborted!\n"; } while (false)
enum Level { Info, Warn, Error };
void log(Level level, const char *text)
{
static const char *levelText[] = { "INFO", "WARNING", "ERROR" };
std::cerr << levelText[level] << ": " << text << '\n';
}
int main()
{
LOG(INFO, "Everything fine. :-)");
LOG(WARN, "Not so fine anymore. :-|");
LOG(FATAL, "Things became worst. :-(");
}
Вывод:
INFO: Everything fine. :-)
WARNING: Not so fine anymore. :-|
ERROR: Things became worst. :-(
Program aborted!
Живая демонстрация на coliru
Еще один пример для последующего вопроса - с шаблонами variadi c вместо макросов:
#include <iostream>
enum Level { Info, Warn, Error, Fatal };
template <typename ...ARGS>
void log(Level level, ARGS&& ... args)
{
static const char *levelText[] = { "INFO", "WARNING", "ERROR", "FATAL" };
std::cerr << levelText[level] << ": ";
(std::cerr << ... << args);
std::cerr << '\n';
if (level == Fatal) std::cerr << "Program aborted!";
}
int main()
{
log(Info, "Everything fine.", ' ', ":-)");
log(Warn, "Not so fine anymore.", ' ', ":-|");
log(Error, "Things became bad.", ' ', ":-(");
log(Fatal, "Things became worst.", ' ', "XXX");
}
Вывод:
INFO: Everything fine. :-)
WARNING: Not so fine anymore. :-|
ERROR: Things became bad. :-(
FATAL: Things became worst. XXX
Program aborted!
Демонстрация в реальном времени на coliru
Должен признать, что мне понадобилась помощь для распаковки параметров - можно найти здесь: SO: Какой самый простой способ напечатать пакет параметров c с использованием std :: ostream? .