Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++: "expected ;" in declaration in template

Tags:

c++

templates

I've been running into the following problem inside a member function of a templated class:

#include <map>
using std::map;
template <typename A,typename B>
class C {
  public:
    B f(const A&,const B&) const;
  private:
    map<A,B> D;
};
template <typename A,typename B>
B C<A,B>::f(const A&a,const B&b) const {
   map<A,B>::const_iterator x = D.find(a);
   if(x == D.end())
     return b;
   else
     return x->second;
}

When I have g++ compile this I get the following error:

Bug.C: In member function 'B C<A,B>::f(const A&, const B&) const':
Bug.C:12: error:expected ';' before 'x'
Bug.C:13: error: 'x' was not declared in this scope

However, when I make a non-templated version of the class and function, with A and B both being int it compiles without a problem. The error is a little mystifying since I can't imagine why it wants a ';' before the 'x'.

like image 389
Victor Miller Avatar asked Dec 05 '22 09:12

Victor Miller


1 Answers

You're missing a typename:

typename map<A,B>::const_iterator x = D.find(a);

Please read Where and why do I have to put the “template” and “typename” keywords?. The reason you need typename here is because A and B are template parameters which means that the meaning of ::const_iterator depends on what A and B are. While to a human the name const_iterator makes it obvious that this is an iterator type, to a compiler it doesn't know if this is a type, a data member, etc.

The compiler will do a syntax check on the first pass before templates are instantiated and by adding typename you letting the compiler know to parse the map<A,B>::const_iterator as a type.

Also, there is a special rule in C++ (shamefully stolen from the linked question):

A name used in a template declaration or definition and that is dependent on a template-parameter is assumed not to name a type unless the applicable name lookup finds a type name or the name is qualified by the keyword typename.

If you do not add typename, the compiler has to assume that it is not a type.

like image 66
Jesse Good Avatar answered Dec 07 '22 00:12

Jesse Good