Смешивая два других решения (рекурсивное от Passer By и C ++ 17-кратное выражение от Ника Мёртина), вы можете написать CreateMessage()
без рекурсии (в аналогичном-кратном выражении) также на C ++11
std::string const & getStr (std::string const & ret)
{ return ret; }
std::string getStr (int val)
{
std::ostringstream ret;
ret << std::hex << std::setw(4) << std::setfill('0') << val;
return ret.str();
}
template <typename ... Ts>
std::string CreateMessage (Ts const & ... args)
{
using unused = int[];
std::string ret = "";
std::string comma = "";
(void)unused { 0, ( ret += comma + getStr(args), comma = ",", 0 )... };
return ret;
}
- РЕДАКТИРОВАТЬ -
ОП спрашивает
Не хотите ли вы научить меня, как этосложить "работает линия?Как мне «прочитать» это?
Ну ... строка следующая
(void)unused { 0, ( ret += comma + getStr(args), comma = ",", 0 )... };
, где unused
- псевдоним (using
) для int[]
.
В нем используется тот факт, что пакет переменных (аргументы шаблона или функции) может быть расширен в контексте инициализации массива в стиле C, а также используется мощность оператора запятой (свойство оператора запятой).из exec / compute и отбрасывать то, что слева от запятой).
Итак, у вас есть расширение (для каждого аргумента в args...
)
( ret += comma + getStr(args), comma = ",", 0 )
где
1) вы добавляете comma + getStr(args)
к ret
, где comma
пуст для первого аргумента и равно ","
(см. (2)) для следующих аргументов
2) для первогооператор запятой отбрасывает значение ret
и присваивает ","
comma
(таким образом, у вас есть пустые comma
в первых ret +=
и ","
для следующих ret +=
3)Второй оператор запятой отбрасывает значение запятой и возвращает 0 для инициализации unuses
Таким образом, ret
увеличивается на All getStr(args)
разделен ","
и неиспользуемый массив инициализируется нулями.
Соблюдайте еще пару моментов:
a) в массиве (без имени unused
)список инициализации, у вас есть начальный и не связанный с переменным ноль ({ 0,
);это необходимо в случае, если список args...
пуст, поэтому строка становится (void)unsed { 0 };
, что допустимо, вместо (void)unused { };
(без этого нуля), что является синтаксической ошибкой
b) unused
предшествует (void)
;это не является строго необходимым, но полезно, чтобы избежать предупреждения типа «объект определен, но не используется».