Analyze the C ++ template (medium)

Source: Internet
Author: User
Type induction in function templates

A very simple but useful example:

//: Arraysize. h

// Uses template type Induction

// Discover the size of an array

# Ifndef arraysize_h

# Define arraysize_h

Template <typename T, int size>

Int ASZ (T (&) [size]) {return size ;}

# Endif // arraysize_h ///:~

The sizeof () operation is not used, but the array size can be pointed out in the compilation phase. You can have more concise methods to calculate the size of the group during compilation.

//: C03: arraysize. cpp

// The ReturnValueOf the Template Function

// ASZ () is a compile-time constant

# Include"../Arraysize. h" 

Int main ()

{

Int A [12], B [20];

Const int sz1 = ASZ ();

Const int sz2 = ASZ (B );

Int C [sz1], d [sz2];

}///:~

Of course, the premise for the program to run normally is that the array size has been given during definition.

Obtain the address of an instantiated function template.

There are many places where you need to get the function entry address. For example, you may have a function whose parameter is a pointer to another function. Of course,

The specified function may be generated from a template. Therefore, you need a method to obtain the function address.

//: C03: templatefunctionaddress. cpp

// Taking the address of a function generated

// From a template.

Template <typename T> void F (t *){}

Void H (void (* PF) (int *)){}

Template <class T>

Void g (void (* PF) (T *)){}

Int main ()

{

// Full type exposition:

H (& F <int> );

// Type Induction:

H (& F );

// Full type exposition:

G <int> (& F <int> );

// Type inductions:

G (& F <int> );

G <int> (& F );

}///:~

This example describes many different topics. First, even if you are using the template, the type must match -- function H () gets a pointer to the function. This function

The void type is returned for parameters of the int type. This is exactly what F features. Second, the function that requires a function pointer as a parameter can also be a template.

Like G. In the main () function, you can see that type Induction also works here. The first call to H () explicitly gives the template parameter F, but from the H (),

So far, it only processes the function pointer of the function that uses int variables as parameters, which can be summarized by the compiler. G () is more interesting, because there are two

Templates to use. The compiler cannot generalize this type, so it will not do anything. However, if F and G are assigned to int, it is easy for the compiler to do anything else.

Member classes in the template

Apply functions to STL Series

Assume that you want to use an STL series container and apply a function to all objects contained in the container. This is because a vector can package

For various types of objects, you need a function that can work together with the vector to process the various objects it contains:

//: C03: applysequence. h

// Apply a function to an STL sequence container

// 0 arguments, any type of returnValue:

Template <class seq, class T, class r>

Void apply (SEQ & SQ, R (T: * f )())

{

Typename seq: iterator it = SQ. Begin ();

While (it! = SQ. End ())

{

(* It)-> * f )();

It ++;

}

}

// A parameter with an indefinite Return Value

Template <class seq, class T, class R, Class A>

Void apply (SEQ & SQ, R (T: * f) (a), a)

{

Typename seq: iterator it = SQ. Begin ();

While (it! = SQ. End ())

{

(* It)-> * f) ();

It ++;

}

}

// Two parameters, the return value is not fixed

Template <class seq, class T, class R,

Class A1, class A2>

Void apply (SEQ & SQ, R (T: * f) (A1, A2 ),

A1 a1, a2 A2)

{

Typename seq: iterator it = SQ. Begin ();

While (it! = SQ. End ())

{

(* It)-> * f) (a1, a2 );

It ++;

}

}

// And so on. The most frequently passed parameters are similar ///:~

The apply () function template uses a reference to the container class and a member pointer to a member function within the container class. It uses an iterator to move data in the stack.

Apply this function to each object.

Note that no STL header files are included in applysequence. H. Therefore, there is no limit to this header file when it is used together with the STL series. Of course, when using

Considering the special nature of iterator, we can only apply it to STL series (don't forget, we must use iterator ).

As you can see, there is more than one apply () Here, so it can reload the function template, each version uses a different number of parameters, because it is

Template, these parameters can be of any type, the only restriction is: this is not a super template, you can create a new template for you.

Test apply () for different versions ().

//: C03: Gromit. h

// The techno-dog. Has member functions

// With various numbers of arguments.

# Include <iostream>

Class Gromit

{

Int Arn;

Public:

Gromit (INT Ali = 1): Ali (ALI + 1 ){}

Void speak (INT)

{

For (INT I = 0; I <Ali; I ++)

STD: cout <"Arn!";

STD: cout <STD: Endl;

}

Char eat (float)

{

STD: cout <"Chomp!"<STD: Endl;

Return'Z';

}

Int sleep (char, double)

{

STD: cout <"Zzz..."<STD: Endl;

Return 0;

}

Void SIT (void ){}

};///:~

Now, the function apply () can be used together with the vector <Gromit *> to create a container and call member functions and included objects:

//: C03: applygromit. cpp

// Test applysequence. h

# Include"Gromit. h" 

# Include"Applysequence. h" 

# Include <vector>

# Include <iostream>

Using namespace STD;

Int main ()

{

Vector <Gromit *> dogs;

For (INT I = 0; I <5; I ++)

Dogs. push_back (New Gromit (I ));

Apply (dogs, & Gromit: Speak, 1 );

Apply (dogs, & Gromit: Eat, 2.0f );

Apply (dogs, & Gromit: sleep,'Z', 3.0 );

Apply (dogs, & Gromit: Sit );

}///:~

Although the definition of apply is a bit complicated, it may not be fully understood by new users, but it is concise and clear, and new users also know how to use it. I think this is just for themselves.

To achieve the goal: You don't need to know the details, you just need to know how to achieve your goals.

Template

//: C03: templatetemplate. cpp

# Include <vector>

# Include <iostream>

# Include <string>

Using namespace STD;

// As long as things are simple,

// This approach works fine:

Template <typename C>

Void print1 (C & C)

{

Typename C: iterator it;

For (IT = C. Begin (); it! = C. End (); It ++)

Cout <* It <" ";

Cout <Endl;

}

// Template-template argument must

// Be a class; cannot use typename:

Template <typename T, template <typename> Class C>

Void print2 (C <t> & C)

{

Copy (C. Begin (), C. End (),

Ostream_iterator <t> (cout," "));

Cout <Endl;

}

Int main ()

{

Vector <string> V (5,"Yow!");

Print1 (v );

Print2 (v );

}///:~

Member function Template

In fact, we can also use apply () As a member function template in a class to make the declaration clearer:

Dogs. Apply (& Gromit: Sit );

As a member of the container class, the definition of apply () is proved to be very clear. To accomplish this, we need to inherit

Add our new functions to the new container. Of course, in order to have the best adaptability, we will use the STL series containers, and we must use

The template tells the compiler that a template parameter is a template, and it can be initialized as a type parameter. See the following:

//: C03: applymember. h

// Applysequence. h modified to use

// Member function templates

Template <class T, template <typename> class seq>

Class sequencewithapply: Public seq <t *>

{

Public:

// 0 arguments, any type of returnValue:

Template <class r>

Void apply (r (t: * f )())

{

Iterator it = begin ();

While (it! = End ())

{

(* It)-> * f )();

It ++;

}

}

// 1 argument, any type of returnValue:

Template <class R, Class A>

Void apply (r (t: * f) (a), a)

{

Iterator it = begin ();

While (it! = End ())

{

(* It)-> * f) ();

It ++;

}

}

// 2 arguments, any type of returnValue:

Template <class R, Class A1, class A2>

Void apply (r (t: * f) (A1, A2 ),

A1 a1, a2 A2)

{

Iterator it = begin ();

While (it! = End ())

{

(* It)-> * f) (a1, a2 );

It ++;

}

}

};///:~

Because they are members of the class, the apply () function does not need so many parameters, and the class to which the iterator belongs does not need to be specified. Of course, begin

() And end () are also member functions of the new class, which all seem so clear and clear. However, the basic code is still the same

//: C03: applygromit2.cpp

// Test applymember. h

# Include"Gromit. h" 

# Include"Applymember. h" 

# Include <vector>

# Include <iostream>

Using namespace STD;

Int main ()

{

Sequencewithapply <Gromit, vector> dogs;

For (INT I = 0; I <5; I ++)

Dogs. push_back (New Gromit (I ));

Dogs. Apply (& Gromit: Speak, 1 );

Dogs. Apply (& Gromit: Eat, 2.0f );

Dogs. Apply (& Gromit: sleep,'Z', 3.0 );

Dogs. Apply (& Gromit: Sit );

}///:~

In terms of concept: You are now calling the apply () method from the dogs container.

Related Article

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.