Definition, use and specialization of templates

Template is the basis of generic programming. The so-called template is to write code that has nothing to do with the type. Template is a means of reuse. Templates are divided into template functions and template classes.
For example, if we want to implement a function that judges whether two numbers are equal, the two parameters passed are different. If there is no template, we need to implement a code for each, but with a template, we only need to implement a code. The compiler will automatically deduce the type of the template parameter based on the passed parameters. Sometimes when the parameter types of the two functions we pass are different, the compiler will report an error. At this time, we need to display the instantiation of the template parameters. The instantiation types are different, and the results obtained are also different.
1. Template
function The definition format of template function:

template  <class 形参名1,class 形参名2...,class 形参名3> 
//这里class也可以换为typename
返回值类型 函数名()
{...}
template <class T>
bool Isequal(T &a, T &b)
{
    return a == b;
}
int main()
{
    string s1("hello");
    string s2 = s1;
    cout<<Isequal(1, 2)<<endl;
    cout << Isequal(s1, s2) << endl;
    cout << Isequal<int>(1, 1.2) << endl;  //模板参数的显示实例化 结果为1
    cout << Isequal<double>(1, 1.2) << endl;  //模板参数的显示实例化,结果为0
    system("pause");
    return 0;
}

2. Template class
What is a class template?
A class template (also known as a generic class or a class-generating class) allows the user to define a pattern for a class that allows certain data members in the class, parameters of default member functions, and return values ​​of certain member functions to take any arbitrary value. Type (including system predefined and user-defined).
If the data types of data members in a class cannot be determined, or the types of parameters or return values ​​of a member function cannot be determined, this class must be declared as a template, and its existence does not represent a specific, actual class, Rather, it represents a class. The member functions in class templates are all template functions (which is true).

What is a template class A
template class is a product of instantiating a class template. New classes can be derived from class templates, both class templates and non-template classes.
Template class definition format

template <class 形参名1,class 形参名2...,class 形参名n>
class 类名
{...}

The following takes the container adapter as an example for analysis

template <typename T> 
class SeqList 
{ 
private:    
    int _size;    
    int _capacity;    
    T* _data;
};

template <class T ,class Container=SeqList<int>>//Container就是一个模板形参,模板实参传什么类型,Container就是什么类型
class Stack
{
public:
    void push(const T &x);
    void pop();
    const T& top();
    bool empty();
protected:
    Container _con;
};

int main()
{
    Stack<int> s1;  
    Stack<int, SeqList< int>> s2;
    system("pause");
    return 0;
}

3. Template class for templates

template <typename T> 
class SeqList 
{ 
private:    
    int _size;    
    int _capacity;    
    T* _data;
};
template <class T ,template <class>  class Container=SeqList>//缺省参数,这里template <class>表示Container是一个模板类型的模板形参
class Stack
{
public:
    void push(const T &x);
    void pop();
    const T& top();
    bool empty();
protected:
    Container<T> _con;
};

4. Specialization of template class

Template specialization in C++ is different from template instantiation. The specific implementation of template parameters under a specific type is called template specialization. Template specialization is also sometimes referred to as template specialization. The full specialization and partial specialization of the template are above the defined template class and cannot exist alone.

Specialization is generally divided into full specialization and partial specialization.
Full specialization: All template parameters in the template are specified as a specific type, and full specialization defines a new type. Produces something completely deterministic, without searching for a suitable specialized implementation at compile time.
Partial specialization: The template parameters in the template are not all determined, and need to be determined at compile time. The
template function can only be fully specialized, and the template class can be fully specialized or partial.
According to the specialization Objects can be divided into
(1) function template specialization: when a function needs to specialize some types, it is called a specialization of a function template. A specialization instance of a
class template:

///  模版特化

template <class T>
int compare(const T left, const T right)
{
    std::cout <<"in template<class T>..." <<std::endl;
    return (left - right);
}


//  这个是一个特化的函数模版
template < >
int compare<const char*>(const char* left, const char* right)
{
    std::cout <<"in special template< >..." <<std::endl;

    return strcmp(left, right);
}
//  特化的函数模版, 两个特化的模版本质相同, 因此编译器会报错
// error: redefinition of 'int compare(T, T) [with T = const char*]'|
//template < >
//int compare(const char* left, const char* right)
//{
//    std::cout <<"in special template< >..." <<std::endl;
//
//    return strcmp(left, right);
//}


//  这个其实本质是函数重载
int compare(char* left, char* right)
{
    std::cout <<"in overload function..." <<std::endl;

    return strcmp(left, right);
}

int main( )
{
    compare(1, 4);

    const char *left = "hello";
    const char *right = "world";
    compare(left, right);

    return 0;
}

When a function call calls a specialized function, the specialized matching function will be called first, rather than instantiated through the function template.
(2) Specialization of class template: When a class needs to specialize some types, it is called the specialization of class template. There are three cases of class template specialization of
template parameters:
· Specialization to absolute type
· Specialize as a reference, a pointer type ·
Specialize
as another template

#include <iostream>
#include <cstring>
#include <cmath>
// general version
template<class T>
class Compare
{
public:
    static bool IsEqual(const T& lh, const T& rh)
    {
        std::cout <<"in the general class..." <<std::endl;
        return lh == rh;
    }
};
// specialize for float
template<>
class Compare<float>
{
public:
    static bool IsEqual(const float& lh, const float& rh)
    {
        std::cout <<"in the float special class..." <<std::endl;

        return std::abs(lh - rh) < 10e-3;
    }
};

// specialize for double
template<>
class Compare<double>
{
public:
    static bool IsEqual(const double& lh, const double& rh)
    {
        std::cout <<"in the double special class..." <<std::endl;

        return std::abs(lh - rh) < 10e-6;
    }
};


int main(void)
{
    Compare<int> comp1;
    std::cout <<comp1.IsEqual(3, 4) <<std::endl;
    std::cout <<comp1.IsEqual(3, 3) <<std::endl;

    Compare<float> comp2;
    std::cout <<comp2.IsEqual(3.14, 4.14) <<std::endl;
    std::cout <<comp2.IsEqual(3, 3) <<std::endl;

    Compare<double> comp3;
    std::cout <<comp3.IsEqual(3.14159, 4.14159) <<std::endl;
    std::cout <<comp3.IsEqual(3.14159, 3.14159) <<std::endl;
    return 0;
}

Specialized to a reference pointer type:

template <class _Iterator>
struct iterator_traits {
  typedef typename _Iterator::iterator_category iterator_category;
  typedef typename _Iterator::value_type        value_type;
  typedef typename _Iterator::difference_type   difference_type;
  typedef typename _Iterator::pointer           pointer;
  typedef typename _Iterator::reference         reference;
};

// specialize for _Tp*
template <class _Tp>
struct iterator_traits<_Tp*> {
  typedef random_access_iterator_tag iterator_category;
  typedef _Tp                         value_type;
  typedef ptrdiff_t                   difference_type;
  typedef _Tp*                        pointer;
  typedef _Tp&                        reference;
};

// specialize for const _Tp*
template <class _Tp>
struct iterator_traits<const _Tp*> {
  typedef random_access_iterator_tag iterator_category;
  typedef _Tp                         value_type;
  typedef ptrdiff_t                   difference_type;
  typedef const _Tp*                  pointer;
  typedef const _Tp&                  reference;
};

Specialize into another template:

// specialize for vector<T>
template<class T>
class Compare<vector<T> >
{
public:
    static bool IsEqual(const vector<T>& lh, const vector<T>& rh)
    {
        if(lh.size() != rh.size()) return false;
        else
        {
            for(int i = 0; i < lh.size(); ++i)
            {
                if(lh[i] != rh[i]) return false;
            }
        }
        return true;
    }
};

We define the parameter type of IsEqual() as a vector type, which is called a semi-specialized type, and we can customize this semi-specialized type as our template class type

// specialize for any template class type
template <class T1> 
struct SpecializedType
{
    T1 x1;
    T1 x2;
};
template <class T>
class Compare<SpecializedType<T> >
{
public:
    static bool IsEqual(const SpecializedType<T>& lh, const SpecializedType<T>& rh)
    {
        return Compare<T>::IsEqual(lh.x1 + lh.x2, rh.x1 + rh.x2);
    }
};

5. Templates do not support separate compilation
Templates do not support separate compilation. The following is why the previously summarized templates do not support separate compilation
https://blog.csdn.net/wyn126/article/details/76733943
6. Template summary:
advantages: Template reuses code, saves resources, and the C++ standard library is generated as a result
Enhances the flexibility of the code
Disadvantages: Templates make the code messy and complex, difficult to maintain, and increase the compilation time
When there template compilation error, the error message is very messy and difficult to maintain Maintaining
each type of parameter generates additional code, resulting in bloated files, excessively long code,

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326432656&siteId=291194637