takecare
takecare

Reputation: 1873

Returning an iterator over a template vector

I've been searching around for something similar but couldn't find it (or what I found wasn't helpful). I'm trying to be able to have an iterator over a vector of a template class, returning it and using it outside the class, as demonstrated in the code below.

#include <iostream>
#include <vector>

using namespace std;

namespace ns {

 template <class T>
 class test {

  private:
   vector<T> container;

  public:
   typedef vector<T>::iterator iterator;

   vector<T>::iterator begin() {
    return container.begin();
   }

   vector<T>::iterator end() {
    return container.end();
   }

 }

};

int main(void) {
 test<int> inters;

 for (ns::test<int>::iterator i = inters.begin(); i != inters.end(); i++) {
  // bla bla bla
 }

 cout << "end" << endl;
 return 0;
}

(you can also check out the code here: http://codepad.org/RuXCYF6T)

I get the following error on line 15:

error: type '__gnu_debug_def::vector<_Tp, std::allocator<_CharT> >' is not derived from type 'ns::test<T>'
compilation terminated due to -Wfatal-errors.

Thanks in advance.

Upvotes: 6

Views: 6785

Answers (3)

riderBill
riderBill

Reputation: 898

There is lots of discussion about templates and typename and dependent names here. I had a hard time finding that page. Here is the answer I posted there:

Apparently the required syntax is slightly different when the function is not a class member. Note the parentheses around the return type--the compiler complained without them.

template<typename T> (typename std::vector<T>::iterator)
              someNonMemberFunction(std::vector<T>& vec, const T& val)
{  return [some std::vector<T>::iterator to an element in vec];
}

Upvotes: 1

Robᵩ
Robᵩ

Reputation: 168616

I got different errors than you (missing typename, missing ;, missing ns::). Apparently, the different errors messages were from different versions of GCC. You ran this under g++ 4.1.2. I use g++ 4.6.1.

After fixing all of the errors, this works for me:

#include <iostream>
#include <vector>

using namespace std;

namespace ns {

 template <class T>
 class test {

  private:
   vector<T> container;

  public:
   typedef typename vector<T>::iterator iterator; // first change: add typename

   typename vector<T>::iterator begin() { // 2nd: add typename
    return container.begin();
   }

   typename vector<T>::iterator end() { // 3rd: add typename
    return container.end();
   }

 }; // 4th: add semi

} // 5th: delete semi

int main(void) {
 ns::test<int> inters; // 6th: add ns::

 for (ns::test<int>::iterator i = inters.begin(); i != inters.end(); i++) {
  // bla bla bla
 }

 cout << "end\n"; // 7th: avoid endl
 return 0;
}

See also: http://codepad.org/gcJBCFOD

Upvotes: 12

Daniel
Daniel

Reputation: 31569

You need to use typename:

typedef typename vector<T>::iterator iterator;

and

typename vector<T>::iterator begin()
typename vector<T>::iterator end()

Edit:
or just use your typedef:

iterator begin()
iterator end()

Upvotes: 4

Related Questions