Перегрузка функции, когда параметры отличаются только эллипсами

У меня есть эта система журналирования, для которой я ищу ярлык для некоторых манипуляций со строками.

Система журналирования используется через функциональные макросы, которые затем пересылаются на один вызов функции. Например, #define Warning (...) LogMessage (eWarning, __VA_ARGS __); .

LogMessage затем выполняет snprintf в новый буфер и затем представляет это сообщение любым объектам журнала случиться быть установленным; printf, OutputDebugString и т. д.

К сожалению, я столкнулся с проблемой, когда имеющийся у нас буфер недостаточно велик, поэтому выходные данные усекаются. Я также понял, что этот метод потерпит неудачу, если в выходном сообщении есть символы процента, как snprintf попытается обработать va_args. Наконец, поскольку большинство наших сообщений журнала не используют va_args, кажется глупым копировать строку только для того, чтобы представить ее регистраторам.

Итак, учитывая мой прототип функции, я смогу перегружаться в зависимости от присутствия из эллипсов? Другими словами, могу ли я предположить, что я могу сделать что-то вроде:

LogMessage(LogLevel, const char* message, ...);
LogMessage(LogLevel, const char* message);

Мои попытки Google не дали ничего особенно полезного (просто показывает мне, что эллипсы будут совпадать, если ничего не происходит, в отличие от моих требований, которые ничего не соответствует), и мой первоначальный удар при реализации просто дал мне неоднозначную ошибку вызова функции.

С ошибкой я должен просто принять, что не могу этого сделать, но мне интересно, если это просто компилятор, который я использую, или, может быть, я делаю это неправильно. Я могу добиться аналогичного эффекта с

// edited version of what I really have to remove our local APIs,
// please excuse minor errors
const char* message = NULL;
char buffer[512];

va_list args;
va_start(args, format);

if(strcmp(format, "%s") == 0) {
    message = va_arg(args, const char*);
}
else if (strchr(format, '%') == NULL) {
    message = format;
}
else {
    vsnprintf(buffer, 512, format, args);
    message = buffer;
}

va_end(args);

... но это кажется расточительным в типичном случае, который можно узнать просто по количеству передаваемых параметров. Например, если эллипсы ничего не соответствуют, выберите другую функцию? Если это не работает, есть ли другой способ, который я могу попробовать, который не требует, чтобы пользователь определился с именем макроса, какая функция будет вызвана? Честно говоря, это не так уж и много об «растрате», когда я понял, что если кто-то случайно сказал Ошибка («Буфер не заполнен на 100%»); в своем сообщении журнала и получил «Буфер не 1007.732873e10ull» как результат.

Редактировать: Хотя мой пример получил ответ «не делай этого», можно ли ответить на сам вопрос?

9
задан dash-tom-bang 2 September 2010 в 16:54
поделиться

1 ответ

Я также понял, что этот метод не сработает, если в выходном сообщении есть символы процента, так как snprintf попытается обработать va_args.

Тогда будьте осторожны. Если задокументировано, что ваша функция принимает строки формата в стиле printf, то ответственность за экранирование любых знаков процента лежит на вызывающем объекте. На самом деле это не ваша работа - пытаться обрабатывать недопустимые строки формата.

Честно говоря, дело даже не в «отходах», как только я понял, что если кто-то случайно сказал Error("Буфер не заполнен на 100%"); в своем сообщении журнала и получил "Буфер не 1007.732873e10ull " как результат.

Я думаю, вам лучше придерживаться идеала C++.В методах Java обычно проверяются допустимые аргументы и выдаются исключения при передаче недопустимых значений. В C++ вы просто позволяете вызывающим абонентам выстрелить себе в ногу. Лучше, чтобы они написали 100%%, чем прыгать через обручи, чтобы защитить их от изучения того, как правильно вызывать вашу функцию.

3
ответ дан 4 December 2019 в 22:26
поделиться
Другие вопросы по тегам:

Похожие вопросы: