21

I'm trying to use the C++ standard library's find algorithm like this:

  template<class T>
  const unsigned int AdjacencyList<T>::_index_for_node(
      const std::vector<T>& list, const T& node
  ) throw(NoSuchNodeException)
  {
    std::vector<T>::iterator iter = std::find(list.begin(), list.end(), node);
  }

When I try to compile, I get these errors:

In file included from ../AdjacencyList.cpp:8:
../AdjacencyList.h: In member function ‘const unsigned int Graph::AdjacencyList<T>::_index_for_node(const std::vector<T, std::allocator<_Tp1> >&, const T&)’:
../AdjacencyList.h:99: error: expected ‘;’ before ‘iter’
../AdjacencyList.h:100: error: ‘iter’ was not declared in this scope
In file included from ../AdjacencyListTest.cpp:9:
../AdjacencyList.h: In member function ‘const unsigned int Graph::AdjacencyList<T>::_index_for_node(const std::vector<T, std::allocator<_Tp1> >&, const T&)’:
../AdjacencyList.h:99: error: expected ‘;’ before ‘iter’
../AdjacencyList.h:100: error: ‘iter’ was not declared in this scope
../AdjacencyList.h: In member function ‘const unsigned int Graph::AdjacencyList<T>::_index_for_node(const std::vector<T, std::allocator<_Tp1> >&, const T&) [with T = int]’:
../AdjacencyList.h:91:   instantiated from ‘const std::vector<T, std::allocator<_Tp1> > Graph::AdjacencyList<T>::neighbours(const T&) [with T = int]’
../AdjacencyListTest.cpp:18:   instantiated from here
../AdjacencyList.h:99: error: dependent-name ‘std::vector::iterator’ is parsed as a non-type, but instantiation yields a type
../AdjacencyList.h:99: note: say ‘typename std::vector::iterator’ if a type is meant

I feel like the "dependent-name ‘std::vector::iterator’ is parsed as a non-type, but instantiation yields a type" bit holds the key to understanding what I'm doing wrong, but my pea-brain cannot extract the meaning.

Update: I needed to add a typename, as per the accepted answer, and also use a const_iterator, so the problematic line of code became:

    typename std::vector<T>::const_iterator iter = std::find(list.begin(), list.end(), node);
Deduplicator
  • 44,692
  • 7
  • 66
  • 118
Josh Glover
  • 25,142
  • 27
  • 92
  • 129
  • There is no `std::find` in the STL. The `std` namespace denotes use of the C++ Standard Library. Meanwhile, taking out the use of `std::find` would have narrowed the question down a little; in this case, you have a dependent name. – Lightness Races in Orbit Apr 19 '11 at 16:54
  • 5
    One of the rare cases where the *last* lines of the error message contain the most useful information... – sth Apr 19 '11 at 16:55
  • 6
    One of the rare cases where an error message from a C++ compiler actually contains a useful, actionable suggestion. ;-) – James McNellis Apr 19 '11 at 16:56
  • @Tomalak: Yes, you are technically correct. For most intents and purposes, STL == C++ standard library, but there are some differences, and I should have been clear. – Josh Glover Apr 19 '11 at 16:58
  • You'll also need const_iterator, not iterator. – Paul Beckingham Apr 19 '11 at 17:01
  • 5
    Ugh again with the STL/stdlib argument... don't people ever get tired of it? – Matteo Italia Apr 19 '11 at 17:05
  • @Matteo: I hear you, and actually didn't know that referring to std::find() as an STL algorithm was incorrect in any way. I did look it up, and I guess it is better to be 100% correct. Still "STL find" has a better ring to it than "ISO C++ standard library find"! ;) – Josh Glover Apr 19 '11 at 17:20
  • @Josh: actually I was saying that pointing out the usual STL/stdlib argument every time someone writes "STL" instead of "the template part of the standard library" or whatever term is felt as correct in the long run is quite boring and useless. – Matteo Italia Apr 19 '11 at 18:45
  • @Matteo: The "boring and useless" was the bit I was agreeing with, albeit as politely as I could. ;) – Josh Glover Apr 20 '11 at 07:46
  • @Josh: uh, sorry, for some reason I understood the exact contrary. Glad that we agree, then `:)` . – Matteo Italia Apr 20 '11 at 14:22

1 Answers1

44
std::vector<T>::iterator iter = /* .... */; 

iterator is a dependent name (effectively, it depends on the type parameter T). Dependent names are assumed not to name types unless you use typename:

typename std::vector<T>::iterator iter = /* .... */;

For more, consider reading the Stack Overflow C++ FAQ entry "Where and why do I have to put “template” and “typename” on dependent names?"

You will also need to use const_iterator, since list is const-qualified. You should probably drop the exception specification as well; it's best to "never write an exception specification."

Community
  • 1
  • 1
James McNellis
  • 348,265
  • 75
  • 913
  • 977
  • Fantastic answer, James! Actually, it was more of a code review than an answer, but code reviews are always welcome. :) – Josh Glover Apr 19 '11 at 17:10