C + + language Learning (17)--Templates

Source: Internet
Author: User
Tags class definition class operator int size

C + + language Learning (17)--Template Introduction

Generics (Generic Programming) refer to the meanings that can be manipulated on a variety of data types. Representative works of generic programming STL is an efficient, generic, interoperable software component.
Generic programming was originally born in C + + to implement STL (Standard Template Library) for C + +. The language support mechanism is the template (Templates). The core idea of a template is a parameterized type, which is to extract the type information from an algorithm or class that is originally specific to a type and extract it into a template parameter T.

Second, function template 1, macro implementation exchange function

Define a macro that swaps two numbers

#define SWAP(t, a, b)   do                      {                           t c = a;                a = b;                  b = c;              }while(0);

The advantage of the macro code block implementation is that code reuse is appropriate for all types, and the disadvantage is the lack of type checking.

2. Function overloading Implementation
#include <iostream>using namespace std;void swap(int &a, int& b){    int t = a;    a = b;    b = t;}void swap(double &a,double b){    double t = a;    a = b;    b = t;}int main(){    int ia = 10; int ib = 20;    swap(ia,ib);    cout<<ia<<ib<<endl;    double da = 10, db = 20;    swap(da,db);    cout<<da<<db<<endl;    return 0;}

The advantage of the function overloading implementation is that a function call is actually made, the C + + compiler does type checking, and the disadvantage is that the function is duplicated by type and cannot be reused.

3. Function template

function templates are special functions that can be called with different types, the key being type parameterization.
The syntax format for a function template is as follows:

template<typename/class 类型参数表>返回类型 函数模板名(函数参数列表){    函数模板定义体}

The template keyword is used to declare the beginning of generic programming.
The TypeName keyword is used to declare a generic type.
A function template can be invoked automatically by deducing the type, or by displaying the specified specific type.

4. Function template Implementation
#include <iostream>using namespace std;template <typename T>void Swap(T& a,T &b ){    T t = a;    a = b;    b = t;}int main(){    int ia = 10; int ib = 20;    Swap(ia,ib); //Swap<int>(ia,ib);    cout<<ia<<ib<<endl;    double da = 10, db = 20;    Swap(da,db); //Swap<double>(da,db);    cout<<da<<db<<endl;    string sa ="china"; string sb = "America";    Swap(sa,sb);    cout<<sa<<sb<<endl;    return 0;}

To determine if a variable is a pointer type example:

template <typename T>bool isPtr(T *p) {    return true;}template <typename T>bool isPtr(T t){    return false;}

A function template that applies only to functions with the same number of arguments and different types, and with the same function body. If the number is different, you cannot use a function template.

5. Function template Analysis

The C + + compiler generates different functions from a function template through a specific type, and the C + + compiler compiles the function template two times, once the function template code is compiled, once the function code after the parameter substitution.

#include <iostream>using namespace std;template <typename T>void Swap(T& a, T& b){    T c = a;    a = b;    b = c;}class Test{};typedef void (*pFuncInt)(int&, int&);typedef void (*pFuncDouble)(double&, double&);typedef void (*pFuncTest)(Test&, Test&);int main(int argc, char *argv[]){    pFuncInt pi = Swap;//Swap<int>    printf("0x%x\n", pi);    pFuncDouble pd = Swap;//Swap<double>    printf("0x%x\n", pd);    pFuncTest pt = Swap;//Swap<Test>    printf("0x%x\n", pt);    return 0;}

The function template itself does not allow implicit type conversions, so strict matching is required for automatic derivation of types, but implicit type conversions can be performed when the specified type parameter is displayed.
The return value type in the function template must display specified.

add<int>(ia,ib);
6. Multi-type parametric function template

A function template can define several different type parameters, but cannot automatically deduce the return value type, you can specify the type parameter from the left-to-right section, and the return value in the actual project as the first type parameter, must be explicitly specified.

#include <iostream>#include <string>using namespace std;template < typename T1, typename T2, typename T3 >T1 Add(T2 a, T3 b){    return static_cast<T1>(a + b);}int main(){    // T1 = int, T2 = double, T3 = double    int r1 = Add<int>(0.5, 0.8);    // T1 = double, T2 = float, T3 = double    double r2 = Add<double, float>(0.5, 0.8);    // T1 = float, T2 = float, T3 = float    float r3 = Add<float, float, float>(0.5, 0.8);    cout << "r1 = " << r1 << endl;     // r1 = 1    cout << "r2 = " << r2 << endl;     // r2 = 1.3    cout << "r3 = " << r3 << endl;     // r3 = 1.3    return 0;}
7. Relationship between normal function and function template

Function templates can be overloaded, the C + + compiler takes precedence over common functions, but if a function template can produce a better match, a function template can be used to qualify only the function template using the empty template argument list.

  #include <iostream> #include <string>using namespace Std;template < typename T >t Max (t A, T B    {cout << "T Max (t A, T b)" << Endl; Return a > B? A:B;}    int max (int a, int b) {cout << "int max (int a, int b)" << Endl; Return a > B? A:B;}    Template < typename T >t Max (t A, T B, t C) {cout << "T Max (t A, T B, t C)" << Endl; Return Max (Max (A, B), c);}    int main () {int a = 1;    int b = 2;                   cout << Max (A, b) << Endl;                 normal function Max (int, int) cout << max<> (A, b) << Endl;               function template max<int> (int, int) cout << Max (3.0, 4.0) << Endl;          function template max<double> (double, double) cout << Max (5.0, 6.0, 7.0) << Endl;               function template max<double> (double, double, double) cout << Max (' a ', +) << Endl; normal function Max (int, int) return 0;}  
Iii. definition of class template 1 and class template

In the C + + language, the idea of a template is applied to a class, so that the implementation of the class does not focus on the specific type of data element, only the functions that the class needs to implement.
The definition syntax for a class template is as follows:

template <typename T>class classname{};

Use the template for identification before the class declaration to &lt;typename T&gt; illustrate the use of the generic type T in the class.
Define member functions within a class

template<typename T>class classname{public:    void push(int size)    {}}

Out-of-class definition functions

template<typename T>void classname<T>::push(T data){}

Class template is instantiated as a template class:

classname<double> object;

A class template is an abstraction of a class that is an instance of a class template.

2. Class Template Application

Class templates can only display specified type parameters and cannot be inferred automatically. A declared generic type parameter can appear anywhere in the class template.
Class templates must be implemented in a header file and cannot be implemented separately in different files. The member functions of a class template need to be defined externally, and each member function is required to add a class template template&lt;typename T&gt; declaration.
Class templates are ideal for working with data of different data types with the same logic, making it a good fit to write code for data structures.

#include <iostream> #include <stdlib.h> #include <stdio.h> #include <string.h>using namespace        Std;template<typename t>class stack{public:stack (int size) {space = new t[size];    top = 0;    } ~stack ();    BOOL IsEmpty ();    BOOL Isfull ();    void push (T data);    T pop ();p rivate:t* space; int top;}; Template<typename T>stack<t>::~stack () {delete []space;} Template<typename T>bool Stack<t>::isempty () {return top = = 0;} Template<typename T>bool Stack<t>::isfull () {return top = = 1024;} Template<typename t>void stack<t>::p ush (T data) {space[top++] = data;} Template<typename t>t Stack<t>::p op () {return space[--top];}    int main () {stack<double> s (+);//stack<string> s (100);    if (!s.isfull ()) S.push (10.3);    if (!s.isfull ()) S.push (20);    if (!s.isfull ()) S.push (30);    if (!s.isfull ()) S.push (40); if (!s.isfull ()) s.Push (50);    while (!s.isempty ()) Cout<<s.pop () <<endl; return 0;}
3. Class Template Analysis

Class templates produce different classes through specific types, where the C + + compiler compiles the class template code itself where it is declared and compiles the code generated after the class template parameter substitution where it is used.
A class template can define several different types of parameters.

#include <iostream>#include <string>using namespace std;template <typename T>class Operator{public:    Operator()    {        cout << "Operator()" << endl;    }    T add(T a, T b)    {        cout << "T add(T a, T b)" << endl;        return a + b;    }    T minus(T a, T b)    {        return a - b;    }    T multiply(T a, T b)    {        return a * b;    }    T divide(T a, T b)    {        return a / b;    }};int main(int argc, char *argv[]){    Operator<int> op1;    cout << op1.add(1, 2) << endl;    cout << op1.add(1, 2) << endl;    Operator<string> op2;    cout << op2.add("D.T.", "Software") << endl;    return 0;}// output:// Operator()// T add(T a, T b)// 3// Operator()// T add(T a, T b)// 3// Operator()// T add(T a, T b)// Hello World

In the code above, the function code in the class template is compiled separately when it is used.

Iv. template specificity 1, class template of the Special

Class templates can be customized, and the following situations require a special class template:
A. Specifying a specific type of implementation
B, some parameter types must display the specified
C. Implement the class template separately according to the type parameter
The specificity of the class template is divided into partial and full specificity. Partial specificity refers to the use of specific rules to constrain type parameters, full specificity refers to the full display of the specified type parameters.
The specificity of a class template is a separate implementation of the template, which is essentially the same class template that the special class template must display to specify each of the type parameters. The compiler automatically prioritizes the special class template.

#include <iostream>using namespace Std;template<typename T1, typename T2>class test{public:void Add (T1 A,        T2 b) {cout << "void Add (T1 A, T2 b)" << Endl;    cout << A + b << endl; }};//Partial Special Template<typename t>class test<t,t>{public:void Add (t A, T b) {cout << void add        (t A, T b) "<< Endl;    cout << A + b << endl;    } void Print () {cout << "class Test <T,T>" << Endl; }};//completely special template<>class test<int,int>{public:void Add (int a, int b) {cout << void Add (i        NT A, int b) "<< Endl;    cout << A + b << endl;    } void Print () {cout << "class test<int,int>" << Endl;    }};int Main (int argc, char *argv[]) {test<int, int> t1;//fully special t1.add (UP);    T1.print ();    Test<double, double> t2;//part of the special T2.add (3.14,2.0);    T2.print (); Test<float,Double> t3;//class template T3.add (3.14,2.0); return 0;}  output://void Add (int a, int b)//3//class test<int,int>//void Add (t A, T B)//5.14//class Test <t,t>// void Add (T1 A, T2 b)//5.14
2, the function template of the special

Function templates only support the full specificity of the template.

#include <iostream>using namespace std;//函数模板template<typename T>bool Equal(T a, T b){    cout << "bool Equal(T a, T b)" << endl;    return a == b;}//函数特化模板template< >bool Equal<double>(double a, double b){    const double delta = 0.00000000000001;    double r = a - b;    cout << "bool Equal<double>(double a, double b)" << endl;    return (-delta < r) && (r < delta);}//函数重载bool Equal(double a, double b){    const double delta = 0.00000000000001;    double r = a - b;    cout << "bool Equal(double a, double b)" << endl;    return (-delta < r) && (r < delta);}int main(int argc, char *argv[]){    Equal<double>(0.1,0.1);//函数特化模板    Equal<int>(10,10);//函数模板    Equal(0.1,0.1);//函数重载    return 0;}// output:// bool Equal<double>(double a, double b)// bool Equal(T a, T b)// bool Equal(double a, double b)

In engineering practice, when you need to overload a function template, the function template is preferred, and function overloading is used when the function template is not specific enough to meet the requirements.

Five, array class template 1, numeric type template

The template parameter can be a numeric parameter, and there is a limit to the numeric template parameters:
A, variables cannot be used as template parameters
B, floating-point numbers cannot be used as template parameters
C, class objects cannot be used as template parameters
Template parameters are processed during the compile phase, so a unique determination is required during the compilation phase.
Use the most efficient way to find 1+2+3+4......+100

#include <iostream>using namespace std;template<int N>class Sum{public:    static const int value = Sum<N-1>::value + N;};template<>class Sum<1>{public:    static const int value = 1;};int main(int argc, char *argv[]){    cout<<Sum<100>::value<<endl;    return 0;}
2. Array templates
#ifndef _array_h_#define _array_h_template< TypeName T, int N >class array{t m_array[n];p ublic:int length ();    BOOL Set (int index, T value);    BOOL Get (int index, t& value);    t& operator[] (int index);    T operator[] (int index) const; Virtual ~array ();}; template< TypeName T, int N >int array<t, N>::length () {return N;} template< TypeName T, int N >bool array<t, n>::set (int index, T value) {BOOL ret = (0 <= index) &&am P    (Index < N);    if (ret) {M_array[index] = value; } return ret;} template< TypeName T, int N >bool array<t, n>::get (int index, t& value) {BOOL ret = (0 <= index) &am    p;& (Index < N);    if (ret) {value = M_array[index]; } return ret;} template< TypeName T, int N >T& array<t, n>::operator[] (int index) {return m_array[index];} template< TypeName T, int N >t array<t, n>::operator[] (int index) const{return m_Array[index];} template< TypeName T, int N >array<t, N>::~array () {} #endif
Six, smart pointer class template

Smart pointers are one of the important class templates of C + + development library and are the main means of automatic memory management, which can avoid memory related problems.

1, STL's smart pointer

The smart pointers in STL are divided into auto_ptr, shared_ptr, weak_ptr, unique_ptr four classes.
Auto_ptr features of smart pointers:
A. At the end of the lifecycle, destroy the pointing memory space
B, cannot point to the heap array, can only point to the heap object
C, a heap of space can only belong to a smart pointer
D, multiple smart pointer objects cannot point to the same space
shared_ptr features of smart pointers:
With a reference counting mechanism, multiple pointers are supported to point to the same object memory space.
WEAK_PTR features of smart pointers:
Weak_ptr is a weak reference that points to an object that shared_ptr manages.
Unique_ptr features of smart pointers:
A pointer object points to a piece of memory space and cannot copy construction and assignment

Examples of using STL smart pointers:

#include <iostream>#include <memory>using namespace std;class Test{    string m_name;public:    Test(const char* name)    {        cout << "Hello, " << name << "." << endl;        m_name = name;    }    void print()    {        cout << "I‘m " << m_name << "." << endl;    }    ~Test()    {        cout << "Goodbye, " << m_name << "." << endl;    }};int main(int argc, char *argv[]){    auto_ptr<Test> pt(new Test("D.T.Software"));    cout << "pt = " << pt.get() << endl;    pt->print();    cout << endl;    auto_ptr<Test> pt1(pt);    cout << "pt = " << pt.get() << endl;//NULL    cout << "pt1 = " << pt1.get() << endl;//    return 0;}
2, the smart pointer in QT

The main smart pointers in

Qt are: Qpointer, Qsharedpointer, Qweakpointer, Qscopedpointer, Qshareddatapoiner, Qexplicitlyshareddatapointer.
Qpointer Smart pointer properties:
A, automatically empty
B when the object it points to is destroyed, the object to which it is not automatically destroyed
multiple Qpointer pointer objects can point to the same memory space, The pointer is automatically empty when the pointing object is destroyed, but the object that is pointed to is not automatically destroyed when the pointer object is destructed.
Qsharedpointer Smart pointer properties:
A, reference-count smart pointer
B, can be freely copied and assigned
C, object to be deleted when reference count is 0 o'clock
QT smart pointer usages:

#include <QPointer> #include <QSharedPointer> #include <qdebug>class test:public qobject{QString m_n        Ame;public:test (const char* name) {qdebug () << "Hello," << name << ".";    M_name = name;    } void Print () {qdebug () << "I ' m" << m_name << ".";} ~test () {qdebug () << "Goodbye," << m_name << ".";}};    int main () {qpointer<test> pt (new Test ("D.t.software"));    Qpointer<test> pt1 (PT);    Qpointer<test> Pt2 (PT);//Multiple Qpointer pointer objects can point to the same memory space Pt->print ();    Pt1->print ();    Pt2->print (); Delete Pt;//qpointer when the object pointed to by the smart pointer is destroyed, the pointer object is placed empty qdebug () << "pt =" << pt;//null qdebug () << "pt1 =" &l    t;< pt1;//null qdebug () << "pt2 =" << pt2;//null qdebug () << Endl;    Qsharedpointer<test> SPT (New Test ("Delphi Tang"));    Qsharedpointer<test> spt1 (SPT); Qsharedpointer<test>Spt2 (SPT);    Spt->print ();    Spt1->print ();    Spt2->print (); The return 0;//pointer object is destroyed when the reference count is 0, and the object that the pointer points to is automatically destructor}
3. Smart pointer class template
#ifndef _SMARTPOINTER_H_#define _SMARTPOINTER_H_template< typename T >class SmartPointer{    T* mp;public:    SmartPointer(T* p = NULL)    {        mp = p;    }    SmartPointer(const SmartPointer<T>& obj)    {        mp = obj.mp;        const_cast<SmartPointer<T>&>(obj).mp = NULL;    }    SmartPointer<T>& operator = (const SmartPointer<T>& obj)    {        if( this != &obj )        {            delete mp;            mp = obj.mp;            const_cast<SmartPointer<T>&>(obj).mp = NULL;        }        return *this;    }    T* operator -> ()    {        return mp;    }    T& operator * ()    {        return *mp;    }    bool isNull()    {        return (mp == NULL);    }    T* get()    {        return mp;    }    ~SmartPointer()    {        delete mp;    }};#endif
Seven, a single class template

Some classes can only have one object in the life cycle of the whole system, that is, singleton mode.
To control the number of objects in a class, you must hide the constructor of the class, that is, the constructor is declared private.
Defines a instance identifier, initialized to null, to view the value of instance when an object is needed, if instance is null, creates an object with instance identity, and returns the value of the instance identity if instance is not empty.

#ifndef _SINGLETON_H_#define _SINGLETON_H_template< typename T >class Singleton{    static T* c_instance;public:    static T* GetInstance();};template< typename T >T* Singleton<T>::c_instance = NULL;template< typename T >T* Singleton<T>::GetInstance(){    if( c_instance == NULL )    {        c_instance = new T();    }    return c_instance;}#endif

Using code:

#include <iostream>#include <string>#include "Singleton.h"using namespace std;class SObject{    friend class Singleton<SObject>;    // 当前类需要使用单例模式    SObject(const SObject&);    SObject& operator= (const SObject&);    SObject()    {    }public:    void print()    {        cout << "this = " << this << endl;    }};int main(){    SObject* s = Singleton<SObject>::GetInstance();    SObject* s1 = Singleton<SObject>::GetInstance();    SObject* s2 = Singleton<SObject>::GetInstance();    s->print();    s1->print();    s2->print();    return 0;}
Eight, template application example

Determine if a variable is a pointer
The C + + compiler matches the invocation priority:
A, overloaded functions
B, function template
C, variable parameter function
You can match the call priority of the C + + compiler by matching the function template to the pointer variable, returning true, the argument function matches the non-pointer variable, and returns FALSE.

template<typename T>bool IsPtr(T *pt){    return true;}bool IsPtr(...){    return false;}

However, because the argument function is the content of the C language, the C + + custom type object cannot be parsed, which can cause the program to crash.

template<typename T>char IsPtr(T* v) // match pointer{    return ‘d‘;}int IsPtr(...)  // match non-pointer{    return 0;}#define ISPTR(p) (sizeof(IsPtr(p)) == sizeof(char))

In the code above, the C + + compiler will perform a function match at compile time, without making calls, avoiding program crashes caused by calling the variable parameter function when the argument is a custom object.

Nine, class and TypeName keywords

The C + + language uses the class keyword to define the class type when introducing the idea of object-oriented programming. In the development of C + + language, generic programming was introduced to directly reuse the class keyword to define the template. But generic programming is not just for class types, and the direct reuse of the class keyword makes the code two semantic. Therefore, C + + directly introduces the TypeName keyword, which is used to declare a generic type in the template definition, explicitly telling the C + + compiler that the identifier for the declaration is type.
The C + + language allows for nested types in a class definition, so when the identifier of a nested type in a custom class type has the same name as a member variable identifier defined in another class type, it will cause two semantics. A non-homogeneous identifier representing the same name may cause two semantics, so the C + + compiler does not recognize the exact meaning of the identifier.

#include <iostream>using namespace std;class Test1{public:    static const int NS = 1;};class Test2{public:    struct NS    {        int value;    };};int a = 0;template <class T>void func(){    T::NS* a;}int main(int argc, char *argv[]){    func<Test1>();    //func<Test2>();//error    //error: dependent-name ‘T:: NS‘ is parsed as a non-type,    //but instantiation yields a type    //say ‘typename T:: NS‘ if a type is meant    return 0;}

In the preceding code, the C + + compiler does not resolve NS in the Func function template to a type, so the C + + compiler will give an error when using TEST2 as a parameter. Therefore, in order for NS to be explicitly declared as a type, the NS identifier needs to be declared using the TypeName keyword. The code is as follows:

#include <iostream>using namespace std;class Test1{public:    static const int NS = 1;};class Test2{public:    struct NS    {        int value;    };};int a = 0;template <class T>void func(){    typename T::NS* a;}int main(int argc, char *argv[]){    //func<Test1>();//error    func<Test2>();    return 0;}

In the preceding code, NS is explicitly declared as a type, so the Func function template will give an error if TEST1 is used as a parameter.

C + + language Learning (17)--Templates

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.