C ++ Study Notes (7) templates and generic programming

Source: Internet
Author: User

Template Introduction
A template is a very important feature of C ++. It is the basis of C ++ generic programming. Some people who are highly biased against C ++ even say that the template is C ++'s

The only contribution (I do not agree with it). We can see the importance of the template in C ++, And the whole STL is based on the template. It can be seen that it is widely used.
An important reason for C ++ to introduce templates is the reuse of algorithms, for example, the following example:

[Cpp]
Bool mless_than (const int & v1, const int & v2 ){
Return v1 <v2;
}
The program is very simple, that is, to compare whether the first parameter is smaller than the second parameter. This algorithm is very common in our program. This is int.

Version. What if we still need a string version, a double version, or even a custom class version? If there is no module

Board, we have to define multiple implementations for it, even if their code is the same, if the algorithm is very long, such as a sorting algorithm, write so many

Version is a lengthy and tedious task. Moreover, we cannot explain what types of algorithms we need to customize in the future. People who write algorithm libraries cannot know.

The type that the user may define. After talking about the necessity of the template, let's take a look at its implementation, or the function just now:
[Cpp]
Template <typename T>
Bool mless_than (const T & v1, const T & v2 ){
Return v1 <v2;
}

The method is also very simple, just call it directly. A smart compiler will automatically export the parameter type of the template for us:

[Cpp] view plaincopy
Bool result = mless_than (2.8, 4.1); // double version
In some cases, compilation cannot push from the called parameters to all template types, or the input parameter types are not the ones we want to use to instantiate the function.

You can also manually specify the template parameter type when using the following method:
[Cpp]
Bool result = mless_than <int> (2.8, 4.1); // double version

In addition to functions, templates can also be used in classes. For example:
[Cpp]
Template <typename T>
Class {
//... Other definition
Private:
T v;
//... Other definition
}

If STL is frequently used, we should be used to the following methods:
[Cpp]
A <int>;

This defines an object A using class a of the int version.
It should be noted that, whether it is a function template or a class template, they are not real functions or classes, it just tells the compiler how to generate a real

Function instances or class instances (not objects here), that is to say, A is not A class, and A <int> is A class.

Let's talk about the introduction of the template. With this preliminary concept, let's take a look at the differences between class and typename.

Class and typename
In the template definition above, I use the typename keyword to define template parameters. If you have learned or understood the template before, you may find that

Another keyword class is used to define template parameters. What are the differences between them? The answer is to define the template parameter here, it

There is no difference between them. Because typename is the keyword introduced later, the key of class may be more common in some old code.
I have said that there is no difference here, but since I have listed a title separately, it means there is something in the middle. Typename in the template

It has some other functions. Before talking about this, let's first understand the concept: nested dependent type names (nested dependency type name ). Test

Consider the following definition:
[Cpp]
Template <typename T>
Void test (const T & c ){
C: key_type * ptr;
// Other implementation
}
Where does c: key_type * ptr mean? If you are familiar with STL, you may say, hey, this is defined using c: key_type.

A pointer ptr is provided in map and set, which indicates the encapsulated key type. However, if there is a fool

A custom class is defined, and a static variable named key_type is defined inside the class, so this statement is no longer a variable definition.

, But a multiplication operation. How does the compiler view this statement? First, let's talk about the concept of the escape dependency type name, such as this definition.

The internal type of the class, while the external class type depends on the template parameter, which is the so-called escape dependency type name. By default, the compiler sets it

It is regarded as a variable name rather than a type name. That is to say, by default, the compiler treats it as a multiplication operation. If we want the compiler to treat it as a class

Type name. You can add the typename keyword before it for modification.
[Cpp]
Typename c: key_type * ptr;

For escape dependency type names like this, we should add the typename keyword when using it. However, there are still exceptions, such

If the nested dependency type is used in the base class list, the typename keyword is not used, because the identifier here may only be the type name.
Nontype Template
All of the above are type templates. In fact, the C ++ template mechanism also supports non-type templates. First, let's take a look

An example of its practical use in STL is the bitmap class:
[Cpp]
Bitset <32> B;

The preceding definition defines a 32-Bit Bitmap class, which uses non-type parameters to specify its size. Let's take a look at the simplicity of a non-type template.

Implementation:
[Cpp]
Template <int SIZE>
Class {
// Some definition
Int data [SIZE];
}

It can be seen that the role of the non-type template parameter here is to specify the SIZE of an array variable maintained internally by A <SIZE>. When we pass parameters,

Non-type parameters are sometimes useful first, for example:
[Cpp]
Template <class T, size_t N> void array_init (T (& parm) [N])
{
For (size_t I = 0; I! = N; ++ I ){
Parm [I] = 0;
}
}

This function initializes an array of any size. Here, it cleverly uses non-type parameters to specify the size of the passed array reference.
Template features and features
The role of a template is to provide a unified implementation method, algorithm logic, or data structure for any type. But sometimes, for some types

The implementation method does not meet our requirements. Consider the initial template function. If we pass a constant string, the compiler will provide an example for us.

The function code is as follows:
[Cpp]
Bool mless_than (const char * const & v1, const char * const & v2 ){
Return v1 <v2;
}

There is a problem with compiling and running. The key is that it compares the addresses of the two strings rather than the strings themselves, which is obviously not what we want. In this situation

In this case, we need to use the special feature of the template to customize a special version for processing strings of C_style. The implementation of the special version is as follows:
[Cpp]
Template <>
Bool mless_than (const char * const & v1, const char * const & v2 ){
Return strcmp (v1, v2) <0;
}

When we pass the C_style string, the compiler will call our special version instead of using the template to generate it for us.
The template features can also be used on the class template. In the special class, we do not have to follow the definition method of the original template. Special definition methods and functions of class templates

The template is roughly similar. However, it must display the specified special template parameter type after the class name.
In addition to the template features, C ++ also allows us to bitrate class templates (function templates do not work), that is, only some template parameters are specified. For example:
[Cpp]
Template <typename T, typename V>
Class {
// Other definition
T d1;
V d2;
};
 
Template <typename T>
Class A <T, int> {
// Other definition
T d1;
Int d2;
};

In the bitwise mode, we convert the template parameter V to int. Note that the bitwise template is still a template class, rather than an actual class.
Template metaprogramming
The so-called template meta-programming does not actually introduce new C ++ features. It is a wonderful usage of C ++ non-type templates and templates. It can

To improve the running efficiency. For example, we want to take the factorial of a constant as the size of a static array.

You can use the template meta programming:
[Cpp]
Template <unsigned N>
Class Factorial {
Public:
Unsigned VALUE = N * factorial <N-1>: VALUE;
};
 
Template <>
Class Factorial <0> {
Public:
Unsigned VALUE = 1;
};

The template class Factorial above is used to calculate Factorial. It uses recursion to calculate the Factorial value we need in the compiler. It is worth noting that

Yes, the recursive exit here is a biased template, which is amazing.
Template compilation Mechanism
After talking about some basic features and usage of the template, let's take a look at the template compilation mechanism. We know that the template only provides the compiler for the compiler.

An instance generation method. The template is instantiated on demand. That is to say, if we put the class template definition in the header file according to our habits

And put the implementation of its member functions in the source file. during the compilation of the Definition source file, no code is generated. In this way, other files are used.

Because it only contains the definition of the class and does not contain the implementation, a class error cannot be found during the connection process. Therefore, all template code must be placed in

In the header file, if you want to facilitate management, you can also put the implementation in the source file, and then use the header file for anti-inclusion. Some children's shoes may worry about resetting

In fact, the template is put in the header file. This C ++ standard runs and the compiler does some special processing on it, so there will be no puts class

Worries about putting the definition in the header file.
In fact, there is still a keyword export in the c ++ standard to solve this problem. However, as there is not much compiler support

No more.
The template compilation mechanism is on demand. The Compiler does not compile the types of on-demand member functions that are not used,

This is important. Some time ago, when I posted a blog on the internet, I met an example from my dear friend. He made a simple template library and tested

There is no problem, but it has encountered a lot of trouble in the actual use process. This is because it does not use all member functions for some types during testing.

And the member function compiler does not compile it, which exposes the problem during use. Therefore, to understand the template compilation mechanism

We will develop our own template library in the future.

Author: justaipanda

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.