Why do we need typename here?
Asked Answered
O

4

19
template<class T>
class Set 
{
public:
   void insert(const T& item);
   void remove(const T& item);
private:
   std::list<T> rep;
}

template<typename T>
void Set<T>::remove(const T& item)
{
   typename std::list<T>::iterator it =  // question here
    std::find(rep.begin(),rep.end(),itme);
   if(it!=rep.end()) rep.erase(it);

}   

Why the typename in the remove() is needed?

Overnice answered 14/7, 2009 at 1:52 Comment(1)
Perhaps edit to make clearer that the line you're talking about is typename std::list<T>::iterator it = std::find(rep.begin(),rep.end(),itme); since I think that's your intention.Cahier
R
27

In general, C++ needs typename because of the unfortunate syntax [*] it inherits from C, that makes it impossible without non-local information to say -- for example -- in A * B; whether A names a type (in which case this is a declaration of B as a pointer to it) or not (in which case this is a multiplication expression -- quite possible since A, for all you can tell without non-local information, could be an instance of a class that overloads operator* to do something weird;-).

In most cases the compiler does have the non-local information needed to disambiguate (though the unfortunate syntax still means the low-level parser needs feedback from the higher-level layer that keeps the symbol table info)... but with templates it doesn't (not in general, though in this specific case it might be technically illegal to specialize a std::list<T> so that its ::iterator is NOT a type name;-).

[*] not just my opinion, but also the opinion of Ken Thompson and Rob Pikes, currently my colleagues, who are busy designing and implementing a new programming language for internal use: that new programming language, while its syntax is mostly C-like, does NOT repeat C's syntax design errors -- it the new language (like e.g. in good old Pascal), syntax is sufficient to distinguish identifiers that must name a type from ones that must not;-).

Refresher answered 14/7, 2009 at 2:8 Comment(4)
iterator could potentially be a static member variable. And by default that it was that compiler assumes it to be. Thus the compiler error.Flaunch
I take it that confirming whether or not said language is called "B++" would be a serious breach of commercial confidentiality? ;-)Colure
Sorry to bring this back from the dead, but 8 years later I'm curious about whether there's any further information whatsoever you can disclose about that programming language. Though I'm not holding my breath.Atli
@Atli Ken Thompson and Rob Pike created Go. Jul 2009 was four months before its open source release.Neither
G
15

If you are talking of typename used with std::list<T>::iterator:

The typename is used to clarify that iterator is a type defined within class std::list<T>. Without typename, std::list<T>::iterator will be considered a static member. typename is used whenever a name that depends on a template parameter is a type.

Graycegrayheaded answered 14/7, 2009 at 2:11 Comment(0)
T
2

I think in general you need both the typename/class T in the class declaration as well as function definitions because you can define full/partial template specifications for function definitions. Ie. you could specialize your remove function for ints, strings, whatever it happens to be. So in this case you're telling the compiler "This is the general template, for any type" then later you might define the same function specified for only integers.

Textualism answered 14/7, 2009 at 1:58 Comment(1)
Ahh this answer is invalid with that clarification, sorry!Textualism
C
1

typename is needed in your declaration of 'it' because otherwise the compiler doesn't know that it's a type declaration rather than an expression.

According to this page, "Use the keyword typename if you have a qualified name that refers to a type and depends on a template parameter."

Cahier answered 14/7, 2009 at 2:12 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.