You need to explicitly provide a template argument for TYPE when invoking the templated version of MakeList, because the compiler doesn't know, based only on the arguments you are providing, what TYPE should be. For instance, given the following call:
MakeList<Politician>(3, politician1, politician2, politician3)
There is no way the compiler could deduce what TYPE is. If you are expecting it to be clever enough and deduce that you are passing objects of type Politician as arguments, well that won't work: C-style variadic functions simply do not provide that information at compile time.
However, in C++11 you could use variadic templates for this purpose, which among other thing would allows you not to pass in the number of subsequent arguments as the first argument. Here is a possible way you could rewrite your variadic MakeList():
namespace detail { template<typename T> void MakeList(std::list<typename std::remove_reference<T>::type>& l, T&& elem) { l.push_back(std::forward<T>(elem)); } template<typename T, typename... Ts> void MakeList( std::list<typename std::remove_reference<T>::type>& l, T&& elem, Ts&&... elems) { l.push_back(std::forward<T>(elem)); MakeList(l, std::forward<Ts>(elems)...); } } template<typename T, typename... Ts> std::list<typename std::remove_reference<T>::type> MakeList( T&& elem, Ts&&... elems) { std::list<typename std::remove_reference<T>::type> l; detail::MakeList(l, std::forward<T>(elem), std::forward<Ts>(elems)...); return l; }
You could then use it this way:
int main() { Politician p1{"John", "Smith"}; Politician p2{"Mike", "Black"}; Politician p3{"George", "White"}; std::list<Politician> myList = MakeList(p1, p2, p3); for (auto const& p : myList) { std::cout << p.name << " " << p.surname << std::endl; } }
Here is a live example.
MakeList<Foo>(3, foo1, foo2, foo3).MakeList?