boost :: format с переменными аргументами шаблона

Предположим, у меня есть printf-подобная функция (используется для регистрации) с использованием идеальной пересылки:

template<typename... Arguments>
void awesome_printf(std::string const& fmt, Arguments&&... args)
{
boost::format f(fmt);
f % /* How to specify `args` here? */;
BlackBoxLogFunction(boost::str(f).c_str());
}

(Я не компилировал это, но моя реальная функция следует этому руководству)

Как я могу «развернуть» аргумент variadic в переменную boost :: format f?

6

Решение

Как обычно с шаблонами с переменными значениями, вы можете использовать рекурсию:

std::string awesome_printf_helper(boost::format& f){
return boost::str(f);
}

template<class T, class... Args>
std::string awesome_printf_helper(boost::format& f, T&& t, Args&&... args){
return awesome_printf_helper(f % std::forward<T>(t), std::forward<Args>(args)...);
}

template<typename... Arguments>
void awesome_printf(std::string const& fmt, Arguments&&... args)
{
boost::format f(fmt);

auto result = awesome_printf_helper(f, std::forward<Arguments>(args)...);

// call BlackBoxLogFunction with result as appropriate, e.g.
std::cout << result;
}

демонстрация.


В C ++ 17 просто (f % ... % std::forward<Arguments>(args)); Сделаю.

11

Другие решения

Я немного погуглил и нашел интересное решение:

#include <iostream>
#include <boost/format.hpp>

template<typename... Arguments>
void format_vargs(std::string const& fmt, Arguments&&... args)
{
boost::format f(fmt);
int unroll[] {0, (f % std::forward<Arguments>(args), 0)...};
static_cast<void>(unroll);

std::cout << boost::str(f);
}

int main()
{
format_vargs("%s %d %d", "Test", 1, 2);
}

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

7

Просто чтобы подвести итог решение void.pointer и подсказки предложены преторианец, Агар Т.С. а также Jarod42, позвольте мне предоставить окончательный вариант (онлайн демо)

#include <boost/format.hpp>
#include <iostream>

template<typename... Arguments>
std::string FormatArgs(const std::string& fmt, const Arguments&... args)
{
boost::format f(fmt);
std::initializer_list<char> {(static_cast<void>(
f % args
), char{}) ...};

return boost::str(f);
}

int main()
{
std::cout << FormatArgs("no args\n"); // "no args"std::cout << FormatArgs("%s; %s; %s;\n", 123, 4.3, "foo"); // 123; 4.3; foo;
std::cout << FormatArgs("%2% %1% %2%\n", 1, 12); // 12 1 12
}

Также, как было отмечено Т.С., с использованием сложить выражение Синтаксис, доступный с C ++ 17, функция FormatArgs может быть переписана более кратким способом

template<typename... Arguments>
std::string FormatArgs(const std::string& fmt, const Arguments&... args)
{
return boost::str((boost::format(fmt) % ... % args));
}
5
А ты уже прошел курс программирования? Супер скидка!
Прокачать скилл $$$
×