3

I have template class in which I am using typedef to declare a map as follows:

#include <map>

template <typename T> class LocalStub {
  typedef std::map<T, T> QueryMap;
  typedef std::pair<T, T> QueryPair;
  typedef QueryMap::iterator QueryMapIterator;

public:
  LocalStub();
  ~LocalStub();
  void AddQuery(const T &, const T &);
  const T &Answer(const T &) const;
private:
  QueryMap _queryMap;
};

Compilation errors

../src/LocalStub/include/localstub.hpp:12: error: declaration of 'class T'
../src/LocalStub/include/localstub.hpp:11: error:  shadows template parm 'class T'
../src/LocalStub/include/localstub.hpp:13: error: template declaration of 'typedef'
../src/LocalStub/include/localstub.hpp:14: error: declaration of 'class T'
../src/LocalStub/include/localstub.hpp:11: error:  shadows template parm 'class T'
../src/LocalStub/include/localstub.hpp:15: error: template declaration of 'typedef'
../src/LocalStub/include/localstub.hpp:16: error: declaration of 'class T'
../src/LocalStub/include/localstub.hpp:11: error:  shadows template parm 'class T'
../src/LocalStub/include/localstub.hpp:17: error: template declaration of 'typedef'
../src/LocalStub/include/localstub.hpp:26: error: 'QueryMap' does not name a type

What am I doing wrong? I don't understand why I am getting that error.

Community
  • 1
  • 1
Hani Gotc
  • 840
  • 11
  • 24
  • => `typedef typename QueryMap::iterator QueryMapIterator;` – AMA Jul 17 '18 at 12:17
  • @AMA excuse my question but why should I add typename> – Hani Gotc Jul 17 '18 at 12:20
  • 3
    You should look at [Where and why do I have to put the “template” and “typename” keywords?](https://stackoverflow.com/questions/610245/where-and-why-do-i-have-to-put-the-template-and-typename-keywords). – user7860670 Jul 17 '18 at 12:22

2 Answers2

2

You forgot to write the keyword typename with QueryMapIterator. Here is the updated version:

template <typename T> class LocalStub {
  typedef std::map<T, T> QueryMap;
  typedef std::pair<T, T> QueryPair;
  typedef typename QueryMap::iterator QueryMapIterator;

public:
  LocalStub();
  ~LocalStub();
  void AddQuery(const T &, const T &);
  const T &Answer(const T &) const;
private:
  QueryMap _queryMap;
};

The reason for this requirement is that the compiler doesn't at this point know whether QueryMapIterator describes a member variable or a nested type

ConsistentProgrammer
  • 1,294
  • 10
  • 14
1

TL;DR - typedef typename QueryMap::iterator QueryMapIterator;

Longer version: QueryMap::iterator is a dependant name and thus it is required that You use typename before typedefing it. Dependant name problem comes from fact that inside the template construction type::something the something may refer either to type, value or function as in below example:

template<class T>
struct foo{
    void bar(){ T::something; }
};

struct baz{
    using something = int;
};

struct bez{
    static const int something = 0;
};

Thus the typename is needed to give additional information to the compiler if the name You are passing refers to a type.

bartop
  • 9,971
  • 1
  • 23
  • 54