#c #stdstring
#c #stdstring
Вопрос:
У меня есть функция ведения журнала, которая использует параметры ‘…’ и создает конечную выходную строку с помощью vsprintf_s
это работает нормально, за исключением того, что мне всегда приходится использовать c_str () для печати строк
сначала я думал, что это не проблема, но добавлять все эти .c_str() после каждой строковой переменной довольно сложно, пока я продолжаю их забывать
Хотя, возможно, гуру C мог бы просветить меня по этому вопросу, есть ли способ заставить мою функцию ведения журнала позаботиться об этом самостоятельно?
void Logger::print(const std::string fmt, ...)
{
va_list args;
int len;
char * buffer;
va_start(args, fmt);
len = _vscprintf(fmt.c_str(), args) 1;
buffer = (char*)malloc(len * sizeof(char));
vsprintf_s(buffer, len, fmt.c_str(), args);
va_end(args);
std::cout << buffer << std::endl;
free(buffer);
}
Спасибо
Комментарии:
1. Я говорю не о формате, а о параметрах, очевидно, поскольку я упомянул, что мне пришлось добавить .c_str()
2. Как насчет чего-нибудь радикально смелого и свежего, например, вообще не использовать
printf
семейство функций?3. лол, лучшая за день 🙂
Ответ №1:
Вы можете добавить два шаблона функции-оболочки с переменными значениями, подобных этому:
#include <type_traits>
template <class Arg>
decltype(auto) prepare(const Argamp; arg)
{
if constexpr (std::is_same_v<Arg, std::string>)
return arg.c_str();
else
return arg;
}
template <class ...Args>
void printWrapper(Argsamp;amp;... args)
{
Log::print(prepare(std::forward<Args>(args))...);
}
и вызывать printWrapper
вместо исходной функции-члена. Обратите внимание, что я предположил, что Log::print
здесь является статической функцией-членом. Если это не так, вам нужно это скорректировать. Теперь это должно сработать:
const std::string hello("hello");
printWrapper("%d %s %s", 42, hello, "world");
Обратите внимание, что для компиляции этого требуется C 17.
Комментарии:
1. Вы отключили все полезные предупреждения, которые современный компилятор мог бы выдавать для строк неправильного формата.
2. @n.m. Да, я согласен с этой проблемой.
3. значит, это не очень хорошая идея? Я не вижу никакой отключающей прагмы… Я попробую
4. @user7082181 это не явное «отключение», а подразумеваемое. Чтобы предупреждение сработало, компилятор должен увидеть строковый литерал исходного формата:
printf("%s", 3)
будет предупреждать,const char* fmt = "%s"; printf(fmt, 3);
не будет выдавать предупреждения в последних версиях clang и gcc