Victor Miller
Victor Miller

Reputation: 451

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

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'.

Upvotes: 4

Views: 4696

Answers (3)

Zagatho
Zagatho

Reputation: 523

You have to add typename:

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

Explanation:
typename states that the name that follows should be treated as a type. Otherwise, names are interpreted to refer to non-types.

Upvotes: 1

Rahul Tripathi
Rahul Tripathi

Reputation: 172398

You have missed the keyword typename, which is required before a qualified name that refers to a type and depends on a template parameter:

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

Upvotes: 2

Jesse Good
Jesse Good

Reputation: 52365

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.

Upvotes: 13

Related Questions