I wanted to get better acquainted with variadic templates, so I decide to try to implement a function like D's writeln()
, just for fun.
void writeln()
{
std::cout << "\n";
}
template<typename T, typename ...Args>
void writeln(T firstArg, Args... extraArgs)
{
std::cout << firstArg;
writeln(std::forward<Args>(extraArgs)...);
}
Usage example:
writeln("hello ", "world ", 42, "\t", 3.141592);
writeln(); // prints just a newline
Next, I implemented a format()
function, which writes to a string instead of cout
:
// Need this because there is no to_string for string in the std namespace.
std::string to_string(const std::string & s)
{
return s;
}
std::string format()
{
return "";
}
template<typename T, typename ...Args>
std::string format(T firstArg, Args... extraArgs)
{
using namespace std;
std::string s = to_string(firstArg);
s += format(std::forward<Args>(extraArgs)...);
return s;
}
// sample:
std::string s = format("hello ", "world ", 42, "\t", 3.141592);
It is uses std::to_string()
for the native types. If I want to print custom types, then I can define a local to_string()
and the overload resolution should find it.
My concerns are:
I haven't had many chances to use variadic templates so far, so I might be missing some caveat here. I was expecting it to be more complicated... Did I miss some corner case?
Is my use of
std::forward
appropriate?Any other comments and suggestion are very welcome.