0

This question is related to : Dependent scope and nested templates, Why do I need to use typedef typename in g++ but not VS? and Nested templates with dependent scope

According to this answer https://stackoverflow.com/a/3311640/1559666 I should add typename to typedef.

The question is - why I getting error?

#include <iostream>

#include <vector>
#include <iterator>


template<typename _Tp, typename _Alloc = std::allocator<_Tp> >
class PtrVector
{
private:
    typedef std::vector<_Tp, _Alloc> VectrorT;
    typedef typename std::vector<_Tp, _Alloc> VT;

public:

    typename std::vector<_Tp, _Alloc>::const_iterator test(){}
    VT::const_iterator test2(){}    // why there is an error here?

};


int main() {
    return 0;
}

http://ideone.com/ghUQ2b

Community
  • 1
  • 1
tower120
  • 5,007
  • 6
  • 40
  • 88
  • 3
    You're using [reserved identifiers](http://stackoverflow.com/questions/228783/what-are-the-rules-about-using-an-underscore-in-a-c-identifier). And you should only have the `typename` when you have `Class::something`. The only one of those statements that fits this explicitly is `test`, but `test2` still relies on the template parameters. – chris Dec 12 '13 at 20:36
  • You'll need `typename` for e.g. resolving `std::vector<_Tp,_Alloc>::iterator` but not for type'defing a template class with the appropriately forwarded template parameters. – πάντα ῥεῖ Dec 12 '13 at 20:41
  • 1
    Because there's no guarantee for the compiler that `VT::const_iterator` is indeed a type, even if `VT` is a type, because `VT` depends on your template parameters. – yzt Dec 12 '13 at 20:50
  • While you're perusing SO questions and answers, perhaps yo may enjoy this one as well: ["Where and why do I have to put the “template” and “typename” keywords?"](http://stackoverflow.com/questions/610245/where-and-why-do-i-have-to-put-the-template-and-typename-keywords/613132#613132) – WhozCraig Dec 12 '13 at 20:54
  • @chris Why they reserved? By which point? – tower120 Dec 12 '13 at 20:56
  • @tower120 click the link he provided in the first sentence of that comment. – WhozCraig Dec 12 '13 at 20:58
  • @tower120, The very first one: *identifiers beginning with an underscore and an uppercase letter* – chris Dec 12 '13 at 21:01

1 Answers1

1

Your Ideone sample fixed:

#include <iostream>

#include <vector>
#include <iterator>


template<typename _Tp, typename _Alloc = std::allocator<_Tp> >
class PtrVector
{
private:
    typedef std::vector<_Tp, _Alloc> VectrorT;
    typedef typename std::vector<_Tp, _Alloc>::const_iterator VTConstIter;
 //         ^^^^^^^^                         ^^^^^^^^^^^^^^^^

public:

    typename std::vector<_Tp, _Alloc>::const_iterator test(){}
 // ^^^^^^^^                         ^^^^^^^^^^^^^^^^
    VTConstIter test2(){}

};


int main() {
    return 0;
}

As for your comments, see these variants also:

// ...
typedef typename VectrorT::const_iterator VTConstIter; // also works
// ...
typename VectrorT::const_iterator test(){} // also works
// ...

I hope that clarifies abit further what's going on in the compilers guts.

πάντα ῥεῖ
  • 1
  • 13
  • 116
  • 190
  • Thank you. I see know that in all mentioned previously answers was your variant. But why typedef std::vector<_Tp, _Alloc> VectrorT not recognized as a type? – tower120 Dec 12 '13 at 21:04
  • @tower120 I have extended my answer a bit, `VectrorT` **is** recognized as a type, if used correctly ... – πάντα ῥεῖ Dec 12 '13 at 21:15