1

This is my List class

template <typename Object>
class List {
    public:
        class iterator {
            ...
        };
    ....
};

This is my function

template <typename Object>
void swapAdjacent(List<Object>::iterator & itrA, List<Object>::iterator & itrB) {

}

After compiling, turns out following error

error: variable or field 'swapAdjacent' declared void

Why it can't work?

If I change my code to following, it can be work

void swapAdjacent(List<int>::iterator & itrA, List<int>::iterator & itrB) {

}

I need help; why the first function can't work?

semsevens
  • 33
  • 5
  • Compiles fine for me. What is your compiler and how are you callling swapAdjacent()? – Manuel Barbe Nov 11 '15 at 09:29
  • compiler: g++ (i686-posix-dwarf-rev0, Built by MinGW-W64 project) 5.2.0 I did not call the function yet. When compiling, the error occurs. – semsevens Nov 11 '15 at 10:00

1 Answers1

5

This seems like an odd compiler error, but it looks like your issue is that you need to tell the compiler that the dependent name List<Object>::iterator names a type. You do this using the typename keyword:

template <typename Object>
void swapAdjacent(typename List<Object>::iterator & itrA, 
                  typename List<Object>::iterator & itrB) {

}

See this question for more information about the typename keyword.

For brevity, you could just use the iterator as the template parameter, which would win you automatic deduction as well:

template <typename Iterator>
void swapAdjacent(Iterator & itrA, Iterator & itrB) {

}
Community
  • 1
  • 1
TartanLlama
  • 59,364
  • 11
  • 141
  • 183
  • Also change the template to should work too – Netwave Nov 11 '15 at 09:34
  • @DanielSanchez that doesn't make a difference; `class` vs. `typename` is a purely stylistic choice unless we're talking about template template parameters pre-C++17. – TartanLlama Nov 11 '15 at 09:37
  • then as list itself is a template you would not need to add typename before, I cant try it right now, but I think that using the typename in the template is forcing it to spread over the definitions – Netwave Nov 11 '15 at 09:59
  • @DanielSanchez that's not right. If you put `class` you would still need to use `typename` to mark the dependent name as a type. `[temp.param]/2:` "There is no semantic difference between `class` and `typename` in a *template-parameter*." – TartanLlama Nov 11 '15 at 10:11
  • @TartanLlama ok, just tested it, i was mixing std::list with List, but anyway, i dont understant it properly, why have you to declare the typenames once more in the template for an existing type already? may we move to a chat please, it really annoys me. :/ – Netwave Nov 11 '15 at 10:37
  • ok, was reading the link post and everything is cristal clear there, thanks :D – Netwave Nov 11 '15 at 10:39