Introduction to the difference between TypeName and class in C + +

Source: Internet
Author: User
Tags traits

  "TypeName" is a keyword in a C + + programming language. quite a synonym for generic programming is another term, "class". This keyword is used to indicate that a non-independent name (dependent names) in a template declaration (or definition) is a type name, not a variable name.

People who learn C + + are very aware of the keyword class, which is used to define classes. After the template is introduced in C + +, the initial method for defining the template is:

template<class T>

here the class keyword indicates that T is a type, and later, in order to avoid confusion about the use of class in these two places, the keyword typename is introduced. It acts as a class to indicate that the following symbol is a type, so that when you define a template, you can use this method:

Template<typename T>

In the template definition syntax, the keyword class functions exactly like TypeName.

Does TypeName only work in the definition of templates? Not really, TypeName. Another effect is: use nested dependency types (nested depended name) as follows:

Classpublic:    int  lengthtype;    .....} Template<class t>void  MyMethod (T myarr) {     typedef typename T::LENGTHTYPE Lengthtype;      = Myarr. GetLength; }

This time TypeName's role is to tell the C + + compiler that the string after TypeName is a type name, not a member function or a member variable, and if there is no typename in front of it, the compiler has no way of knowing T:: Lengthtype is a type or a member name (static data member or static function), so compilation cannot be passed.

C + + Proverbs: Understanding the two implications of TypeName: What is the difference between class and TypeName in the following template declarations (stencil declaration)?

Template<class t> class Widget; Uses "class"
Template<typename t> class Widget; Uses "TypeName"

Answer: Nothing different. Class and TypeName mean exactly the same thing when you declare a template type parameter (the parameter for the templates). Some programmers prefer to use class at all times because it's easier to type in. Other people (including myself) prefer TypeName because it implies that this parameter is not necessarily a class type. A few developers use TypeName when any type is allowed, while retaining the class to only accept user-defined types (user-defined type). But from a C + + point of view, class and typename mean exactly the same thing when declaring a template parameter.

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

Suppose we have a template for a function that can get an object that can be assigned to ints in a stl-compatible container (STL compliant container). This function is further assumed to simply print the value of its second element. It is a confused function that is implemented in a confused way, and as I write below, it cannot even compile, but please put it aside-there is a way to discover my stupidity:

Template<typename c>//print 2nd element in
void print2nd (const c& Container)//container;
{
This 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; Copy that element to an int
Std::cout << value; Print the INT
}
}

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

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

Nested dependent name (nested dependent name) can cause parsing difficulties. For example, suppose we are more foolish to start print2nd in this way:

Template<typename c>
void print2nd (const c& Container)
{
C::const_iterator * x;
...
}

It looks as if we were declaring X as a local variable (c::const_iterator) that points to the. But it does look just because we know that c::const_iterator is a type. But what if c::const_iterator is not a type? What happens if C has a static data member (static member) called Const_iterator? What if x happens to be the name of a global variable (globally variable)? In this case, the above code is not declaring a local variable, but instead becomes c::const_iterator multiplied by x! Of course, this may sound silly, but it is possible, and the person writing the C + + parser must consider all possible inputs, or even stupidity.

Until c becomes known, there is no way to know whether C::const_iterator is a type or not, and C is not known when template print2nd is parsed. C + + has a rule that resolves this ambiguity: if the parser encounters a nested dependent name (nested dependent name) in a template, it assumes that the name is not a type, unless you tell it otherwise. By default, nested dependent name (nested dependent name) is not types (type). (There is an 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 was assumed to
...//not being a type

Why this is not legal C + + should now be clear. The Declaration (Declaration) of ITER is only meaningful when c::const_iterator is a type, but we do not tell C + + it is, and C + + assumes it is not. To change this situation, we have to tell C + + C::const_iterator to be a type. We put the TypeName in front of it to do this:

Template<typename c>//This is valid C + +
void print2nd (const c& Container)
{
if (Container.size () >= 2) {
TypeName C::const_iterator Iter (Container.begin ());
...
}
}

The general rule is simple: when you involve a nested dependent type name (nested dependency type name) in the template, you must put the word typename in front of it next to it. (Again, I would like to describe an exception later.) )

TypeName should only be used to identify nested dependent type name (nested dependency type name); Other names should not be used. 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 (nested dependency type name) (it is not nested inside of something that relies on a template parameter (templated parameter)), so when declaring container it does not have to be TypeName before , but C::iterator is a nested dependent type name (nested dependent types name), so it must be typename pre-set.

The exception to the rule "TypeName must precede nested dependent type names" ("TypeName must be placed before nested dependency type name") is that TypeName does not have to be placed before a list of base classes ( base class list), or in a member initialization list (member initialization lists) as a base classes identifier (base class identifier) nested dependent type 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 in a base class list or
}//As a base class identifier in a
...//mem. Init. List:typename Required
};

Such contradictions are annoying, but once you gain a bit of experience in your experiences, you will hardly care about it.

Let's take a look at the last example of a typename, because it is representative of the real code you see. Let's say we're writing a function template that gets a iterator (iterator), and we're going to do a local copy of the object (an iterator) pointing to iterator 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 a standard traits class (the normal attribute Class) use, in C + + is said to be "the type of thing pointed to by objects of type Itert" ("The object is of the kind Itert") The type of the object being pointed to "). This statement declares a local variable (temp) that is the same type as Itert objects, and initializes the temp with the object that ITER points to. If Itert is vector<int>::iterator,temp, it is the int type. If Itert is list<string>::iterator,temp, it is a 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 (parameter), we have to let it be typename pre-placed.

If you think reading Std::iterator_traits<itert>::value_type is annoying, imagine that it is the same thing that represents it. If you are like most programmers and are afraid to enter it multiple times, then you need to create a typedef. For traits member names (attribute member names) such as value_type, a common practice is that typedef name is the same as traits member name, so a local typedef like this is usually defined as:

Template<typename itert>
void Workwithiterator (Itert iter)
{
typedef typename STD::ITERATOR_TRAITS<ITERT>::VALUE_TYPE Value_type;

Value_type temp (*iter);
...
}

Many programmers initially found that the "typedef typename" is not well-tied, but it is a reasonable accompanying result involving nested dependent type names (nested dependency type name) rules. You'll get used to it pretty quickly. You have a strong motive after all. How much time do you need to enter TypeName Std::iterator_traits<itert>::value_type?

As a conclusion, I should mention the difference between the compiler and the compiler about the execution of the rules around TypeName. Some compilers accept code that is missing when required TypeName, while some compilers accept code that is not allowed to TypeName, and a few (usually old) refuse to TypeName appear where it is necessary to appear. This means that the interaction of typename and nested dependent type names (nested dependent type name) can cause some minor portability problems.

Things to Remember

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

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

Introduction to the difference between TypeName and class in C + +

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.