I am trying to understand some C++ syntax:
template<class T> class Foo { Foo(); template<class U> Foo(const Foo<U>& other); }; template<class T> Foo<T>::Foo() { /*normal init*/ } template<class T> template<class U> Foo<T>::Foo(const Foo<U>& other) { /*odd copy constructed Foo*/ }
So, I wrote code like this, and it happens to compile fine in windows and linux. What I don’t understand is why the copy constructor has two templates defined as so. Basically, I had to expirment a bit before I found the correct syntax and I would like to know why that particular syntax is correct, and not something like template<class T, class U>.
It has to have separate
templateclauses for each template that is involved. Here, two templates are involved, that all deserve their (non-empty) template clauses:FooConsider this case which fails because of the ambiguity as to where the parameter
Ubelongs toNow, what is up with the parameter
U? Sure the compiler could guess it could belong tof, but guesswork is not what the compiler likes 🙂 The existing rule says that depending on the nesting of templates, template clauses appear in the right order. Everything is clear then.Even if one comes up with a rule how to match the parameters to arguments of the templates involved (so far i don’t see a real difficulty in doing that), it would be inconsistent. Because as of now, one template clause lists all parameters that the corresponding template accepts. Much like a function parameter list. If we would put everything into one clause, that clear semantic could be broken – not to mention that when we put the definition into the class again, all of a sudden the template would get its own clause:
It’s much more natural when we have separate template clauses that catch each their own arguments. So, the syntax for the above wrong definition is
Now, also the reader of the code immediately sees that this is a definition of a member template, and not a (potential accidentally declared but unused) second parameter for
A.