This is how (unconstrained) templates are supposed to work. Types and
values that depend on at least one template parameter are /dependent/
and the compiler cannot (usually) safely reject above assignment
without having a concrete instantiation. To give you a better picture
of the problem, lets assume your definition of template ListNode looks
like this:
template<class T>
struct ListNode {
};
If that would be the only possible way to instantiate a ListNode
instance, the compiler could easily find out that above line
ListNode<T> q = first;
could never be well-formed, because there is no conversion from
ListNode<T>* to ListNode<T>.
The problem is, that the compiler cannot safely assume that, because
there *could* be any specialization (partial or not partial), that
*would* allow a conversion from a pointer. E.g. someone could write:
template<>
struct ListNode<int> {
ListNode(ListNode*);
};
This means, unless the compiler has a concrete specialization and can
look at all possible conversion paths, it cannot really reject the
code as ill-formed, because it is *potentially well-formed*.
Only expressions that are not dependent or some very rare combinations
that can never be valid in any case, can be rejected without having a
concrete instance available.
HTH & Greetings from Bremen,
Daniel Krügler