About the difference between TypeName and class in templates in C + + __c++

Source: Internet
Author: User
Tags traits

C + + Proverbs: Understanding the two meanings of TypeName

Question: What is the difference between class and TypeName in the following template declarations (template declaration)? Template<class t> class Widget; Uses "class"
Template<typename t> class Widget; Uses "TypeName"

Answer: no different. When declaring a template type parameter (template type parameter), class and typename mean exactly the same thing. Some programmers prefer to use class at all times because it's easier to enter. Other people (including myself) prefer TypeName because it implies that this parameter is not necessarily a class type. A small number of developers use TypeName when any type is allowed, while retaining the class to situations where only user-defined types (user-defined types) are accepted. But from the C + + point of view, class and typename mean exactly the same thing when declaring a template parameter (template parameter).

However, C + + does not always treat class and typename as equals. Sometimes you have to use TypeName. To understand this, we have to discuss the two names you will be involved in a template (template).

Suppose we have a template for a function that can get an object held in a stl-compatible container (STL compliant container) that can be assigned to INTs. Further assume that this function simply prints the value of its second element. It is a silly function that is implemented in a confused way, and as I write below, it cannot even compile, but put these aside--there is a way to discover my stupidity: template<typename c>//print 2nd element in
void print2nd (const c& Container)//container; The
{
//is not valid c++!
if (container.size () >= 2) {
C::const_iterator iter (Container.begin ()); Get iterator to 1st element
++iter;//move Iter to 2nd element
int value = *iter; NT
Std::cout << value;//print the int
}
}

I highlighted two local variables (locals) in this function, ITER and value. The type of ITER is c::const_iterator, a type that relies on template parameter (template parameter) C. The name of a template (template) that relies on a template parameter (template parameter) is called dependent names (dependent name). When a dependent names (dependent name) is nested inside a class (class), I call it the nested dependent name (the nested dependent name). C::const_iterator is a nested dependent name (nested dependent). In fact, it is a nested dependent type name (the nested dependent types name), that is, a nested dependent name (the nested dependent name) that involves a type (type).

Another local variable (locals) value in print2nd has an int type. int is a name that does not depend on any template parameter (template parameters). Such names are known as non-dependent names (not dependent names). (I can't figure out why they don't call it independent names (no dependent name). If, like me, you find the term "non-dependent" to be a repulsive thing, you resonate with me, but "non-dependent" is the term for this kind of name, so, like me, turn your eyes and give up your ego. )

Nested dependent name (nested dependency name) can cause parsing difficulties. For example, suppose we are more stupid to start print2nd:template<typename in this way c>
void print2nd (const c& Container)
{
C::const_iterator * x;
...
}

It looks as if we are declaring X as a local variable (locals) that points to c::const_iterator. But it seems so just because we know that c::const_iterator is a type. But what if c::const_iterator is not a type? If C has a static data member (static), it happens to be called const_iterator. And if x happens to be the name of a global variable variable. In this case, the code above is not declaring a local variable, but rather becoming c::const_iterator times x. Of course, this may sound silly, but it is possible, and the person writing the C + + parser must consider all possible inputs, even folly.

Until c becomes known, there is no way to know if C::const_iterator is a type, and when template (template) print2nd is parsed, C is not known. C + + has a rule that resolves this ambiguity: if the parser encounters a nested dependent name (a nested dependent name) in a template (template), it assumes that the name is not a type, unless you tell it otherwise. By default, nested dependent name (nested dependency name) is not types (type). (with one exception to this rule, I'll tell you later.) )

Remember this, and then look at the beginning of print2nd: Template<typename c>
void print2nd (const c& Container)
{
if (Container.size () >= 2) {
C::const_iterator iter (Container.begin ()); This name is assumed to
..//Not be a type

Why this is not legal C + + should now be clear. ITER's declaration (declaration) only makes sense when c::const_iterator is a type, but we don't tell C + + it is, and C + + assumes it is not. To change the situation, we have to tell C + + C::const_iterator is a type. We do this by placing the TypeName in front of it: template<typename c>//This is valid C + +
void print2nd (const c& Container)
{
if (Container.size () >= 2) {
TypeName C::const_iterator Iter (Container.begin ());
...
}
}

The common rule is simple: whenever you involve a nested dependent type name (a nested dependency) in a template (template), you must place the word typename immediately before it. (Again, I'm going to describe an exception later.) )

TypeName should be used only to identify nested dependent type name (nested dependency type name); Other names should not use it. For example, this is a function template that obtains a container (container) and a iterator (iterator) in this container (container): Template<typename c>// TypeName allowed (as is "class")
void f (const c& container,//TypeName not allowed
TypeName C::iterator ITER); TypeName Required

C is not a nested dependent type name (a nested dependent-name) (it is not nested within something that relies on a template parameter (template parameter), so it does not have to be container before it is declared , but C::iterator is a nested dependent type name (the nested dependency type name), so it must be typename forward.

The exception to the "TypeName must precede nested dependent type names" ("TypeName must be placed before nested dependent type name") rule is that TypeName is not required to be placed in a list of base classes ( The nested dependent type of a base classes identifier (base class identifier) in or in a member initialization list (members initialization lists) Name (nested dependency type name). For example: Template<typename t>
Class Derived:public base<t>::nested {
Base class List:typename not
Public://Allowed
explicit Derived (int x)
: base<t>::nested (x)//Base class identifier in MEM
{
Init. List:typename not allowed
 
TypeName Base<t>::nested temp; Use of nested dependent type
..//Name not in a base class list or
}//As a base class identifier in a
...//Mem. Init. List:typename Required
};

This is a nasty paradox, but once you gain a little experience in your experience, you hardly care about it.

Let's look at the last example of a typename, because it's representative of the real code you see. Let's say we're writing a function template (an iterator), and we're going to do a local copy of the object (iterator) that the iterator (iterator) points to. temp, we can do this: template <typename itert>
void Workwithiterator (Itert iter)
{
TypeName Std::iterator_traits<itert>::value_type Temp (*iter);
...
}

Don't let Std::iterator_traits<itert>::value_type scare you. That is just the use of a standard traits class (Standard attribute Class), in C + +, "the type of thing pointed to by objects of type Itert" ("Object of type Itert The type of thing to point to "). This statement declares a local variable (locals) (temp) that has the same type of thing as the Itert objects, and initializes the temp with the object that ITER points to. If Itert is vector<int>::iterator,temp is the int type. If Itert is list<string>::iterator,temp, it is the string type. Because Std::iterator_traits<itert>::value_type is a nested dependent type name (nested dependency type name) (Value_type nested in Iterator_ Traits<itert> inside, and Itert is a template parameter (template parameter), we have to let it be TypeName front.

If you think that reading Std::iterator_traits<itert>::value_type is annoying, imagine the same thing as the one to represent it. If you're like most programmers, you're scared to enter it multiple times, then you need to create a typedef. For a traits member names such as Value_type, a common practice is that the TypeDef name is the same as the name traits, so a local typedef is usually defined as this: Template<typename itert>
void Workwithiterator (Itert iter)
{
typedef typename STD::ITERATOR_TRAITS<ITERT>::VALUE_TYPE Value_type;
Value_type temp (*iter);
...
}

Many programmers initially discovered that the "typedef typename" were not very harmonious, but it was a reasonable by-product of the nested dependent type names (nested dependency type name) rule. You'll get used to it quite quickly. You have a strong motive after all. How long does it take you to enter TypeName Std::iterator_traits<itert>::value_type?

As a closing remark, I should mention the difference between the compiler and the compiler's implementation of the rules around TypeName. Some compilers accept code that is missing when required TypeName, and some compilers accept code that exists when TypeName is not allowed; and a handful of (usually old) refuse to appear in the TypeName where it must appear. This means that the interaction of the typename and nested dependent type names (nested dependent type names) can cause some minor portability problems.

Things to Remember

• Class and TypeName are interchangeable when declaring template parameters (template parameters).

• Use TypeName to identify nested dependent type names (nested dependency type name), in base class lists (base class list) or in a member initialization list (members initialization lists) as a A base class identifier (base type identifier).

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.