1. Naming template parameters:
Some advanced scripting languages, such as Perl and PL/SQL, support named parameters when calling their function parameters, that is, parameters can be passed in different order during the call, instead, p can be passed by parameter name. Let's take a look at the following code example:
Template <typename Policy1 = DefaultPolicy1,
Typename Policy2 = DefaultPolicy2,
Typename Policy3 = DefaultPolicy3,
Typename Policy4 = DefaultPolicy4>
Class BreadSlicer {
......
}
The template class above contains four template parameters. If you want to specify a parameter that is not the default parameter, you must also specify all the previous template parameters, such:
BreadSlicer <default1_y1, default1_y2, Custom>. However, we prefer the calling method BreadSlicer <Policy3 = Custom>. The following provides some specific implementations. Be sure to pay attention to the key notes in the Code:
1 # include <stdio. h> 2 # include <typeinfo> 3 # include <conio. h> 4 5 // define different policy classes first. 6 class DefaultPolicy1 {}; 7 class DefaultPolicy2 {}; 8 class defapolicpolicy3 {}; 9 class DefaultPolicy4 {}; 10 11 // this Class will be the base class of all Policy classes. It provides the type redefinition of the default four policies. 12 // Therefore, by default, these four policies will be the four policies of BreadSlicer. 13 class DefaultPolicies {14 public: 15 typedef default1_y1 P1; 16 typedef defapolic1_y2 P2; 17 typedef defapolicpolicy3 P3; 18 typedef defaulty4 P4; 19 }; 20 21 // here, the ultpolicyargs intermediate class is provided, and the class is allowed to inherit 22 // defapolicpolicies in the form of virtual inheritance, first, to avoid the Ambiguity Caused by multiple inheritance of the same base class, and at the same time 23 // It is also to facilitate the inheritance of other classes. 24 class DefaultPolicyArgs: virtual public defapolicpolicies {25}; 26 27 // The second constant template parameter is provided here to avoid repeated inheritance of the same base class. 28 template <typename Base, int D> 29 class Discriminator: public Base {30}; 31 32 // if there is no constant template parameter for Discriminator, it is very likely that the same base class will be inherited. 33 template <typename Setter1, typename Setter2, 34 typename Setter3, typename Setter4> 35 class PolicySelector: public Discriminator <Setter1, 1>, public Discriminator <Setter2, 2>, 36 public Discriminator <Setter3, 3>, public Discriminator <Setter4, 4> {37}; 38 39 template <typename PolicySetter1 = DefaultPolicyArgs, 40 typename PolicySetter2 = defapolicpolicyargs, 41 typename PolicySetter3 = DefaultPolicyArgs, 42 typename PolicySetter4 = DefaultPolicyArgs> 43 class BreadSlicer {44 public: 45 // In the implementation after this class, do not directly use template parameters, but use Policies: P1, P2, p3, P4, etc. 46 typedef PolicySelector <PolicySetter1, PolicySetter2, PolicySetter3, PolicySetter4> Policies; 47 void DoTest () {48 printf ("Policies: P1 is % s \ n", typeid (Policies :: p1 ). name (); 49 printf ("ies: P2 is % s \ n", typeid (ies: P2 ). name (); 50 printf ("ies: P3 is % s \ n", typeid (ies: P3 ). name (); 51 printf ("Policies: P4 is % s \ n", typeid (Policies: P4 ). name (); 52} 53}; 54 55 template <typename Policy> 56 Class policypolicis: virtual public DefaultPolicies {57 public: 58 typedef Policy P1; // rewrite the P1-based typedef in DefaultPolicies. 59}; 60 61 template <typename Policy> 62 class Policy2_is: virtual public DefaultPolicies {63 public: 64 typedef Policy P2; // rewrite the P2-based typedef in DefaultPolicies. 65 }; 66 67 template <typename Policy> 68 class Policy3_is: virtual public DefaultPolicies {69 public: 70 typedef Policy P3; // rewrite the P3-based typedef in DefaultPolicies. 71}; 72 73 template <typename Policy> 74 class Policy4_is: virtual public DefaultPolicies {75 public: 76 typedef Policy P4; // rewrite the P4-based typedef in DefaultPolicies. 77}; 78 79 class CustomPolicy {}; 80 81 int main () {82 BreadSlicer <Policy3_is <CustomPolicy> bc; 83 bc. doTest (); 84 getch (); 85 return 0; 86} 87 // Policies: P1 is class defapolicpolicy188 // Policies: P2 is class DefaultPolicy289 // Policies :: p3 is class CustomPolicy90 // Policies: P4 is class DefaultPolicy4
In the preceding example, all template parameters are derived classes of DefaultPolicies. When the BreadSlicer object is declared, different Derived classes will overwrite typedef in different ultpolicpolicies.
Ii. Recursive template mode:
This is a general template design mode, that is, the derived class passes itself as a template parameter to the base class, such:
Template <typename DerivedT>
Class Base {
......
};
Class MyDerived: public Base <MyDerived> {
......
};
Based on this model, there is a well-known use case, namely [MeyersCounting], designed by Scott Meyers, author of Objective C ++. By inheriting the base classes in the following code, all derived classes can implement the class instance counting function. In the base class below, a static member indicating the object count will be included, and the value will be incremented during the base class construction, and the value will be decreased during the analysis, see the following sample code:
1 # include <stdio. h> 2 # include <conio. h> 3 4 template <typename CountedType> 5 class ObjectCounter {6 private: 7 static size_t count; 8 9 protected: 10 ObjectCounter () {11 ++ ObjectCounter <CountedType> :: count; 12} 13 ObjectCounter (ObjectCounter <CountedType> const &) {14 ++ ObjectCounter <CountedType >:: count; 15} 16 ~ ObjectCounter () {17 -- ObjectCounter <CountedType>: count; 18} 19 20 public: 21 static size_t liveCount () {22 return ObjectCounter <CountedType >:: count; 23} 24 }; 25 26 template <typename CountedType> 27 size_t ObjectCounter <CountedType >:: count = 0; 28 29 // The C ++ compiler instantiates different types of class objects based on different template parameters. Therefore, the static members used vary with template parameters. 30 class MyClass: public ObjectCounter <MyClass> {31}; 32 33 int main () {34 MyClass mc1; 35 printf ("The count of MyClass is % d \ n ", myClass: liveCount (); 36 {37 MyClass mc2; 38 printf ("The count of MyClass is % d \ n", MyClass: liveCount ()); 39} 40 printf ("The count of MyClass is % d \ n", MyClass: liveCount (); 41 getch (); 42 return 0; 43} 44 // The count of MyClass is 145 // The count of MyClass is 246 // The count of MyClass is 1