4

For some reason, the following code gives the error Symbol 'TemplateBase' could not be resolved.:

template <typename T>
class TemplateBase
{
    TemplateBase(std::map<std::string, T>::const_iterator anIterator)
    { }
};

class SubClass : public TemplateBase<int>
{
    SubClass(std::map<std::string, int>::const_iterator anIterator) :
        TemplateBase<int>(anIterator) //Error: Symbol 'TemplateBase' could not be resolved.
    { }
};

Strangely, no error appears when I remove the ::const_iterator and only std::map<std::string, int> remains:

template <typename T>
class TemplateBase
{
    TemplateBase(std::map<std::string, T> aMap)
    { }
};

class SubClass : public TemplateBase<int>
{
    SubClass(std::map<std::string, int> aMap) :
        TemplateBase<int>(aMap) //No error.
    { }
};

Additionally, the following function gives no error either, so it really seems related to the combination of a template base class call with a const_iterator:

void function()
{
    std::map<std::string, int>::const_iterator anIterator;
    TemplateBase<int> aTemplateBase(anIterator); //No error
}

Is there some rule against using const_iterator as an argument for base class template constructors that I'm unaware of? Or is this a compiler bug?

I'm compiling with MinGW 64bit 4.9.0 on Windows 7, using C++11.

Aberrant
  • 3,423
  • 1
  • 27
  • 38

1 Answers1

6

When you use a nested type that depends on a template type you need to use the typename keyword:

TemplateBase(typename std::map<std::string, T>::const_iterator anIterator)
{ }
Adam
  • 16,808
  • 7
  • 52
  • 98
  • Huh, didn't expect it was even legal to put the word typename there. This fixed it for me, thanks. But why is this necessary for `std::map::const_iterator` and not for `std::map`? – Aberrant May 30 '14 at 21:42
  • 2
    @Aberrant Because you're not referring to a nested type in the second case. Also, do you feel [this](https://stackoverflow.com/questions/610245/where-and-why-do-i-have-to-put-the-template-and-typename-keywords?rq=1) is a duplicate of your question? My close vote is binding, so I want to check with you before I do that. – Praetorian May 30 '14 at 21:43
  • @Praetorian I guess it probably is. I can't find this specific syntax in there (`ClassName(typename someComplexlyDerivedNestedIdontevenType)`) but judging by how extensive the keyword is explained, it is probably in there in a way. I'll make sure to read the whole thing thoroughly. So yeah, closing this question is fine, I suppose. – Aberrant May 30 '14 at 21:55
  • To explain, without the `typename` keyword the compiler can't tell whether `const_iterator` is a typename or a variable name. You might write a template specialization of `std::map` after this that changes that detail. – M.M May 30 '14 at 22:20
  • @Aberrant : See this FAQ for more information on `typename`: [What is the template `typename` keyword used for?](http://www.comeaucomputing.com/techtalk/templates/#typename) – ildjarn May 31 '14 at 01:52