Apply a very popular sentence (a lot of beautiful programming or code ). I want to see Chapter 3 what modern c ++ design can feel is the beauty of recursion. The typelist introduced here is a perfect example of recursive deduction.
In fact, the definition of typelist is very simple. Is a simple empty definition with head and tail.
Template
Struct typelist
{
Typedef T head;
Typedef U tail;
};
However, if this macro definition is added, the original definition can be extended infinitely.
# Define loki_typelist_1 (T1): Loki: typelist
# Define loki_typelist_2 (T1, T2): Loki: typelist
# Define loki_typelist_3 (T1, T2, T3): Loki: typelist
When
Here, Loki is the main Loki introduced in this book.
Library. namespace. With this recursive call, you can create loki_typelist_50 or even loki_typelist_100. When
It makes him more powerful. He is powerful enough to add a new class at will, delete one of the classes, or delete redundant duplicates.
Let's look at it in a simple way:
Template struct length;
Template <> struct Length
{
Enum {value = 0 };
};
Template
Struct length <>
{
Enum {value = 1 + Length: Value };
};
This
The implementation in the program refers to the recursive idea everywhere. How does a template such as length display the value. If tlist is nulltype (nulltype is defined here)
A class that indicates null, as described in the previous chapter). The length is 0. If typelist is typelist, the value is 1 +.
Length: value, that is, 1.
Of course, if it is a class defined by loki_typelist_x, return the length of loki_typelist _ (x-1) plus 1. This is achieved through repeated headers. (Just
Is to remove the T in the typelist) there are a lot of such operations.
Template struct typeat;
Template
Struct typeat, 0>
{
Typedef head result;
};
Template
Struct typeat, I>
{
Typedef typename typeat: Result result;
};
Typeat
This template is used to extract the class corresponding to an index in the typelist, which is very intuitive. Similarly, if the index is 0, the head of the current typelist is returned
Is the type corresponding to the first class. What if I is not 0? As with the first definition, after removing the head, find the I-1 starting from the first item of tail in the entire typelist. Recursion,
Or recursion. Such a definition can be seen everywhere. I really admire Andrei.
Alexandrescu. Genius! As I read this book, I feel increasingly pale, as if I have never learned C ++.
Let's continue to look at the definition of a slightly complex point.
Template struct indexof;
Template
Struct indexof
{
Enum {value =-1 };
};
Template
Struct indexof, T>
{
Enum {value = 0 };
};
Template
Struct indexof, T>
{
PRIVATE:
Enum {temp = indexof: Value };
Public:
Enum {value = (temp =-1? -1: 1 + temp )};
};
This
A definition is a bit confusing at first glance, but it is clear after careful analysis. If typelist is empty,-1 is returned, indicating that the T is not included,
If the first one is t, the index such as 0 is returned. This process also conforms to the general write recursion process. First, find the convergence condition, and then perform recursion successively :)
If the first one is head, but not T, what should we do? Our value depends on temp, and obtaining temp depends on
Value. If t is not found in indexof, the value is-1, and the value of typelist is-1, because no. If you can find the previous
If the value starts at least 0, you can add 1 in sequence. Now it's quite clear.
The definition of the segment can define such a large thing:
Template struct length;
Template struct typeat;
Template struct indexof;
Template struct append;
Template struct erase;
Template struct eraseall;
Template struct noduplicates;
Template struct replace;
Template struct replaceall;
Template struct reverse;
Template struct mostderived;
Template struct derivedtofront;
But what is the use of these definitions ?? This is a good question. This mode helps us to create classes that meet specific requirements for certain columns without any effort.
Template Class unit>
Class genscatterhierarchy;
// Genscatterhierarchy specialization: typelist to Unit
Template Class unit>
Class genscatterhierarchy , Unit>
: Public genscatterhierarchy
, Public genscatterhierarchy
{
Public:
Typedef typelist Tlist;
Typedef genscatterhierarchy Leftbase;
Typedef genscatterhierarchy Rightbase;
};
// Pass an atomic type (non-typelist) to Unit
Template Class unit>
Class genscatterhierarchy: Public Unit
{
Typedef unit leftbase;
};
// Do nothing for nulltype
Template Class unit>
Class genscatterhierarchy
{
};
Template
Struct holder
{
T value _;
};
Typedef genscatterhierarchy Widgetinfo;
Just like the example in the book. The genscatterhierarchy definition combines the advantages of typelist. A simple widgetinfo defines at least these classes: Holder , Holder And holder There is also a certain inheritance relationship. Obviously, their widgetinfo inherits from them.
So this statement is natural.
Widgetinfo OBJ;
String name = (static_cast &> (OBJ). Value _;
Amazing. What's more, the scattered (scattered) inheritance relationship genscatterhierarchy can be changed to linear. That is genlinearhierarchy. I don't want to talk about it in detail. I believe it will be designed in the future when I introduce the container design in Loki. Let's get there today.