Есть ли способ добиться этого для разных типов?
Работает точно так, как вы написали.
Но, если вы можете использовать C ++ 17,Я предлагаю избегать рекурсии и использовать свертывание шаблона следующим образом
template <typename ... Args>
void write (std::ostream& s, Args ... args)
{ (..., write(s, args)); }
Если вы можете использовать только C ++ 11 или C ++ 14, вы можете смоделировать свертывание шаблона, инициализируя неиспользуемый массив
template <typename ... Args>
void write (std::ostream& s, Args ... args)
{
using unused = int[];
(void)unused { 0, (write(s, args), 0)... };
}
В любом случае, полный рабочий пример вашего рекурсивного пути
#include <iostream>
template <typename T>
void write (std::ostream & s, T const & t)
{ s << "- " << t << std::endl; }
template <typename T, typename ... Args>
void write (std::ostream& s, T first, Args ... args)
{ write(s, first); write(s, args...); }
int main ()
{
write(std::cout, 1, 2.2, "three", 4l);
}