Visual Studio compiles this code fine, but gcc only lets it compile without the Template operator. With the Template operator it gives the following errors:
Line 29: error: expected `;' before "itrValue"
class Test
{
public:
Test& operator<<(const char* s) {return *this;} // not implemented yet
Test& operator<<(size_t s) {return *this;} // not implemented yet
Test& operator<< (const std::list<const char*>& strList)
{
*this << "count=" << strList.size() << "(";
for (std::list<const char*>::const_iterator itrValue = strList.begin();
itrValue != strList.end(); ++itrValue)
{
*this << " " << *itrValue;
}
*this << ")";
return *this;
}
template <class T>
Test& operator<< (const std::list<T>& listTemplate)
{
*this << "count=" << listTemplate.size() << "(";
// this is line 28, the next line is the offending line
for (std::list<T>::const_iterator itrValue = listTemplate.begin();
itrValue != listTemplate.end(); ++itrValue)
{
*this << " " << *itrValue;
}
*this << ")";
return *this;
}
};
GCC is right, const_iterator is a type, and template dependant in the template operator<<, you need to tell the compiler it's a type and not a variable:
To complete @Pieter answer, which is correct, some more info on how templates are processed. First of all, templates are only compiled whenever they are instantiated, so that if you do not instantiate the template for a given type then the code will never be compiled.
Now, when you do instantiate a template, there is a two steps validation of the template code. First the template is verified for correctness regardless of what the instantiation type is. To check with a simpler to understand example:
During the first phase, the template is checked for syntax correctness without considering what A really is. At this time the syntax A::type could be a type by the name of 'type' or it could be a static variable by the same name.
In the first case, type is indeed a type, in the second it is not. Now the standard states that if it is really a type then the programmer of the template must state so to inform the compiler with the syntax above:
Now, to complete the processing, the compiler must check that the template code is not only correct in itself, but that when it is instantiated with the particular type T it is also correct. This is what the compiler performs during the second stage of validation. It applies the type and rechecks for errors.
In your case, it is a little more controversial, as everyone (but the compiler) knows that std::list::const_iterator is a type for any given T. Well, it does not need to be. From a language standpoint, some code could provide a template specialization for a particular data type T that is different to the general list template. The compiler cannot know whether that could be so.
Note that it would be horribly wrong to specialize a template in the std namespace with something that changes behavior in as much as redefining the iterator types. But the compiler sees std namespace just as any other namespace, and list as any other templated class.
I think it's worth telling you about the other disambiguations. For
typename
i already answered another one here.The other one is template. Look here:
Note how we had to use both template and typename disambiguations. The typename told the compiler
The template told the compiler