The print statement in the constructor's definition doesn't get printed, isn't the constructor calling correct in main? I know I am missing some point here, please point out.
#include <iostream>
#include <typeinfo>
template <typename T> class List
{
public:
template <typename T2> List (List<T2> const&);
};
template <typename T> template <typename T2> List <T> :: List (List <T2> const&)
{
std :: cout << "\nType name:" << typeid (T2).name();
}
int main ()
{
List <int> kk (List <int>);
return 0;
}
There are a couple of things wrong in your code that you might not be aware of.
List<int> kk( List<int> );
That line is not a variable definition, but rather the declaration of a function that takes a List<int>
as argument and returns a List<int>
, so that effectively will not call any constructor. That is know as the most-vexing-parse (you can look at different versions of it by searching in SO, or in the C++ FAQ lite)
The second issue is that you cannot possibly create any instance of the an instantiated type of List
, the reason being is that the only constructor that you are providing is a templated constructor that takes a second List<U>
as argument. That effectively disables the default constructor, so the only way of creating a List<T>
is by already having a List<U>
, and that is not possible. You can add the default constructor back:
template <typename T>
class List {
public:
List() {}
template <typename U>
List( List<U> const & ) {} // prefer const& as that will avoid unnecessary copying
};
And now you can write:
List<int> l = List<int>(); // this will call List<int>::List( List<int> const & )
And yet, that will still not call the constructor you want. The reason is a little obscure, but when copy constructing an element of a template, the compiler will not use a templated constructor. In the code above, it will implicitly define a copy constructor by doing member-wise copy constructor of the methods and call that generated constructor. That means that in most occasions where you want to provide a templated constructor you want to also provide a non-templated copy constructor.
To actually call that constructor you would have to provide a different type:
List<int> l = List<double>();
Since the types actually differ, the compiler cannot copy construct, will find that the provided templated constructor is the best overload candidate and call it.