0

So, I'm developing a templated Vector class for an assignment and I came across a few issues that I solved by Googling, but I still want to know why what I was doing was wrong. First issue is that I had:

template <typename T>
class Vector
{
    ...
    template <typename T2>
    Vector(const Vector<T2> &other);
}

template <typename T, T2>
Vector<T>::Vector(const Vector<T2> &other)
{
    ...
}

this was giving me an "unable to match function definition to an existing declaration" in VS11. I fixed it by putting the template definitions on separate lines:

template <typename T>
template <typename T2>
Vector<T>::Vector(const Vector<T2> &other)
{
    ...
}

but I still don't know why this was needed. I know that the first definition is valid for functions/classes that use multiple templates in them, but why is it the case that the syntax changes when you mix a templated class with a templated member function?

My second question has to do with types inside of template classes. When writing the iterator I had functions such as:

template <typename T>
class Vector
{
    ...
    class iterator
    {
        ...
        iterator &operator++(void);
    }
}

template <typename T>
Vector<T>::iterator &Vector<T>::iterator::operator++(void)
{
    ...
}

which gave me "dependent name is not a type" and I later found out that I needed to add "typename" in front:

template <typename T>
typename Vector<T>::iterator &Vector<T>::iterator::operator++(void)
{
    ...
}

After Googling the warning number (which resulted in an error), I realized why the error exists, but it isn't too obvious why the compiler doesn't know that Vector<T>::iterator is a type. I mean, it has the definition of the class, so...

Anyway, thanks for clarifying these few things for me!

Duncan
  • 980
  • 6
  • 17
  • 1
    Can I suggest that you drop the second part of the question and take [this existing post](http://stackoverflow.com/questions/1123080/why-do-we-need-typename-here) as an answer? (The first part can remain of course -- having just one question per post is much better anyway.) – jogojapan Feb 27 '13 at 06:44
  • Who downvoted this? OP has a legit question about template syntax. – Stephen Lin Feb 27 '13 at 07:35

1 Answers1

1
template <typename T>
template <typename T2>
Vector<T>::Vector(const Vector<T2> &other)
{

Is also valid to be written as

template <typename T> template <typename T2>
Vector<T>::Vector(const Vector<T2> &other)
{

You just need (?) to write it out as two sets, since they are after all two sets of parameters - first one is for the class, second one for the function.

typename for dependant types and related rules (this for template base class members and template for template member functions(?) ) have to do with something called "Two Phase Lookup". This is however badly implemented (as in not) on MSVC++, so it may not throw as many errors as a conforming implementation might.

More info - http://blog.llvm.org/2009/12/dreaded-two-phase-name-lookup.html http://womble.decadent.org.uk/c++/template-faq.html#disambiguation http://eli.thegreenplace.net/2012/02/06/dependent-name-lookup-for-c-templates/

Community
  • 1
  • 1
Karthik T
  • 31,456
  • 5
  • 68
  • 87
  • 1
    To be clear (in case it's not), it's because OP is defining a templated member of a template: template refers to class and template refers to the member of the class. (I'm pretty sure OP knows that extra whitespace is not significant in C++ :D) – Stephen Lin Feb 27 '13 at 06:39
  • @StephenLin Thats what I mention isnt it? The OP specifically mentions "seperate lines", which is what I wanted to correct – Karthik T Feb 27 '13 at 06:40
  • eg: if Vector were a template taking two template parameters with a non-templated constructor, then `template Vector::Vector(...)` would be correct: most of the time you define template member functions inline with the class definition anyway so you never come across this. – Stephen Lin Feb 27 '13 at 06:40
  • Yeah but the main issue is why it's two separate templates not that it's on two different lines, as far as I can tell. Just wanted to make it clearer. – Stephen Lin Feb 27 '13 at 06:42
  • Oh snap, I made a typo. My original implementation was with `template ` <- separated by a comma – Duncan Feb 27 '13 at 06:43
  • Well, now I'm not sure what you're asking about. Anyway, it's definitely two templates...one template defined inside another, which is distinct from one template having two parameters. – Stephen Lin Feb 27 '13 at 06:46
  • Anyway, thanks for your help though. It was informative. Also, just for a little clarification: I was getting an error for the second part because the compiler didn't know the type during the first phase? That's kind of silly IMO since it should at least know that iterator is defined as a class. – Duncan Feb 27 '13 at 06:47
  • (so `template Vector::Vector(...)` would work if Vector were non-templated but its constructor was templated on two parameters) – Stephen Lin Feb 27 '13 at 06:48
  • @StephenLin I was wondering why/in what situations you needed to separate template definitions (since I know that it is usually done with `template ` though I think I understand the difference now – Duncan Feb 27 '13 at 06:49
  • w.r.t. to `typename`: it's not always that easy. Anyway, `typename` was not required for dependent names originally and compilers got along fine usually, but the problem is a template basically isn't fully evaluated until its instantiated and template arguments are substituted so it made it hard for the compiler to verify anything about the template without knowing ahead of time what's supposed to be a type and what isn't. With `typename`, the compiler can at least do some minimal verification that a template is well-formed before instantiation. – Stephen Lin Feb 27 '13 at 06:51