string Format(string format_string, T1 p1, T2 p2, ..., TN pn)
The Format()
function takes a copy of format_string
and replace occurrences of "___"
with the remaining parameters to the function (p1
, p2
,...). The first occurrence of "___"
will be replaced by p1
, the next by p2
, and so on. If there are no occurrences of "___"
the remaining parameters will be appended to the string delimited by spaces. If the parameters are not strings they will be converted to strings with operator<<(ostream,x)
. Format will return the modified string.
For example:
Format("The ___ is ___ years", "fox", 8, "old")
evaluates to:
"The fox is 8 years old"
The implementation follows:
struct FormatEmptyStruct {};
const string FormatPlaceholder("___");
template<class T>
inline FormatEmptyStruct OStreamWriteT(ostringstream& os, const std::string& sFormat, string::size_type& iCurrentPos, const T& t)
{
auto iNextPos = sFormat.find(FormatPlaceholder, iCurrentPos);
if (iNextPos == std::string::npos)
{
os.write(sFormat.data() + iCurrentPos, sFormat.size() - iCurrentPos);
iCurrentPos = sFormat.size();
os << " ";
os << t;
}
else
{
os.write(sFormat.data() + iCurrentPos, iNextPos - iCurrentPos);
os << t;
iCurrentPos = iNextPos + FormatPlaceholder.size();
}
return {};
}
struct EmptyStruct {};
inline string Format() { return ""; }
template <class... Args>
inline string Format(const string& sFormat, const Args&... args)
{
ostringstream os;
string::size_type iCurrentPos = 0;
initializer_list<FormatEmptyStruct>{ OStreamWriteT(os, sFormat, iCurrentPos, args)... };
if (!sFormat.empty())
os.write(&sFormat.front() + iCurrentPos, sFormat.size() - iCurrentPos);
return os.str();
}