Mixing other two solutions (the recursive one from Passer By and the C++17 fold expression one from Nick Mertin), you can write CreateMessage()
without recursion (in a simil-fold expression way) also in 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;
}
-- EDIT --
The OP asks
Would you like to teach me how that "simil-fold" line works? How should i "read" it?
Well... the line is the following
(void)unused { 0, ( ret += comma + getStr(args), comma = ",", 0 )... };
where unused
is an alias (using
) for int[]
.
It uses the fact that a variadic pack (template or function arguments) can be expanded in the context of a C-style array initialization and also uses the power of the comma operator (the propriety of comma operator of exec/compute and discard what is on the left of the comma).
So you have the expansion (for every argument in args...
) of
( ret += comma + getStr(args), comma = ",", 0 )
where
1) you add comma + getStr(args)
to ret
, where comma
is empty for first argument and equal to ","
(see (2)) for the following arguments
2) the first comma operator discard the value of ret
and assign ","
to comma
(so you have an empty comma
in first ret +=
and ","
for followings ret +=
3) the second comma operator discard the value of comma and return 0 to the initialization of unuses
So ret
is incremented with all getStr(args)
separated by ","
and the unused array is initialized with zeros.
Observe another couple of points:
a) in the array (the un-named unused
) initialization list, you have a starting and not variadic related zero ({ 0,
); this is necessary in case the args...
list is empty, so the line become (void)unsed { 0 };
, that is legal, instead of (void)unused { };
(without that zero) that is a syntax error
b) unused
is preceded by (void)
; this isn't strictly necessary but useful to avoid a warning of type "object defined but not used".