Iterator inside class template

Hello,

I'm trying to declare an iterator to a list whose container type is a structure that I have declared inside of a template class. For some reason, I have no problem declaring a reference to this list, but I can not declare an iterator. Here is the code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include<vector>
#include<list>

#define DEFAULT_SIZE 8

using namespace std;

template <class keyClass,class valClass> 
class myHash {
public:
  int insert(keyClass& key,valClass& val);

  typedef struct keyVal {
    keyClass key;
    valClass val;
  } keyVal;  

private:
  int hash_function(keyClass& key);

  vector<list<keyVal> > table;
};

template <class keyClass,class valClass> int myHash<keyClass,valClass>::hash_function(keyClass& key) {

  int i;
  int sum = 0;
  unsigned char* ptr = (unsigned char*)&key;
  for(i=0;i<sizeof(key);i++) {
    sum+=ptr[i];
  }

  return sum;
}

template <class keyClass,class valClass> int myHash<keyClass,valClass>::insert(keyClass& key,valClass& val) {

  int bin = hash_function(key) % table.size();

  // Check if its there
  const list<keyVal>& l = table[bin];

  list<keyVal>::iterator iter = l.begin();

  // Look for key in list of keyVal

  return 0;
}


I get the following compile error:


jon-mac:CODE jonny5cents$ g++ -c test.cpp
test.cpp: In member function ‘int myHash<keyClass, valClass>::insert(keyClass&, valClass&)’:
test.cpp:43: error: expected `;' before ‘iter’

Here's the part that is giving me the issue:
1
2
3
4
5

  // Check if its there
  const list<keyVal>& l = table[bin];

  list<keyVal>::iterator iter = l.begin();


The reference line is fine, but the iterator line gives me a compile error.

Any ideas?

Many thanks,

jon
class list<keyVal>::iterator iter = l.begin(); //class or typename
Wow, this works. Thanks ... But I don't know why. I've used iterators many times before but I have never had to put class in front of the declaration. For instance, here:

http://www.yolinux.com/TUTORIALS/LinuxTutorialC++STL.html

When do you have to prepend class in front of an iterator declaration?

Thanks again,

jon

I typically use typename instead of class as I find that to be less confusing, but I guess it's the same either way.

Anyway this has to do with dependent names vs. indepenedent names in templates. Here's a link that's somewhat on point:

http://www.parashift.com/c++-faq-lite/templates.html#faq-35.18


Basically if you're in a template, and a type you're using depends on a templated type, you have to give the typename hint.

For example:

1
2
3
4
5
6
7
8
9
10
11
template <typename T> void foo()
{
  vector<T>::iterator i; // bad, vector<T>::iterator might not be a type
    // depending on what 'T' is.  For example, there might be a specialization
    // where iterator is defined as a member var instead of a type.

  typename vector<T>::iterator i;  // OK

  vector<int>::iterator i;  // OK, the compiler doesn't need to know what 'T'
    // is in order to know what iterator is.  Therefore you don't need typename here
}




On another note, you have a const correctness issue:

1
2
3
  const list<keyVal>& l = table[bin];  // if 'l' is const

  typename list<keyVal>::const_iterator iter = l.begin(); // then you can only get const_iterators 
Last edited on
Topic archived. No new replies allowed.