Valid tive C ++ clause 42: Understanding the double meaning of typename

Source: Internet
Author: User

In the template declaration, the class and typename keywords have the same meaning.

Template <class T> class widget;

Template <typename T> class widget;

Sometimes you must use typename,

You can refer to the following two types of names in template:

Template <typename C>
Void print2nd (const C & container)
{
If (container. Size ()> = 2)
{
C: const_iterator ITER (container. Begin ());
++ ITER;
Int value = * ITER;
STD: cout <value;
}
}

The type of ITER is C: const_iterator. What actually depends on the template parameter C. If the names in the template depend on a template parameter, they are called dependent names ). If the subordinate name is nested in the class, it is called the nested dependent name ). C: const_iterator is such a name nested slave name.

Value Type Int. Does not depend on the name of any template parameter. It is called a non-dependent name ).

Nested subordinate names may cause difficulties in parsing:

Template <typename C>
Void print2nd (const C & container)
{
C: const_iterator * X;
}

It seems that we declare a local variable, which is a pointer pointing to a C: const_iterator. However, it is considered so because we "Already Know" C: const_iterator is a type. What if C: const_iterator is not a type? If C has a static member variable that happens to be named const_iterator. Out of date X happens to be a global variable name, so the above Code is a multiplication action, C: const_iterator multiplied by X. The person who writes the C ++ parser must worry about all possible input.

Before we know C, there is no way to know whether C: const_iterator is of a type. When the compiler starts parsing the template print2nd, It is not sure what C is.

C ++ has a rule to resolve this ambiguous state: If the parser encounters a nested slave name in the template, it assumes that the name is not of a type unless you tell it to be. By default, the subordinate name is not a type. There is also an exception.

Therefore, the above code is not a valid C ++ code. We must tell C ++ that C: const_iterator is a type. Just put the keyword typename next to it:

Template <typename C> // This legal C ++ code
Void print2nd (const C & container)
{
If (container. Size ()> = 2)
{
Typename C: const_iterator ITER (container. Begin ());
++ ITER;
Int value = * ITER;
STD: cout <value;
}
}

Typename is only used to identify the nested subordinate type name; other names should not have it.

Template <typename C>
Void F (const C & container, // typename is not allowed
Typename C: iterator ITER); // you must use typename

The exception to the rule "typename must be the prefix word of the nested subordinate type name" is that typename cannot appear before the nested subordinate type name in the base classes list, it cannot be used as a base class modifier in the member initialization list (member initialization list. For example:

Template <typename T>
Class derived: public base <t >:: nested {// "typename" is not allowed in the base class list"
Public:
Explicit derived (int x)
: Base <t>: Nested (x) // "typename" is not allowed in MEM. init. List"
{
Typename base <t>: Nested temp; // The nested subordinate type is neither in the base class list nor in MEM. init. List,
} // Add typename as a base class Modifier
};

Let's take a look at a typename example: a function template that accepts an iterator, and we plan to make a replica temp for the object referred to by the iterator:

Template <typename itert>
Void workwithiterator (itert)
{
Typename STD: iterator_traits <itert>: value_type temp (* ITER );
}

This is an application of the standard trait class (cla47), which is equivalent to saying "the type of the object referred to by the Type itert ". If the itert is vector <int >:: iterator, the temp type is int. If the itert is list <string >:: iterator, the temp type is string. Because STD: iterator_traits <itert>: value_type is a nested subordinate type name (value_type is nested in iterator_traits <itert>, while itert is a template parameter ), therefore, typename must be placed before it.

So long, you will definitely want to create a typedef. For traits Member names such as value_type, it is generally used to set the typedef name to represent a traits member name:

Template <typename itert>
Void workwithiterator (itert)
{
Typedef typename STD: iterator_traits <itert >:: value_type;
Value_type temp (* ITER );
}

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.