[C++ Series Notes] 04 C++ Generic Programming

Generic programming

Templates are a generic implementation, the generic is the template thought.

The essence of generics is the parameterization of types.

Function template

Function template

  • Basic grammar

    template<class T>
    void function(T param1, T param2){
          
          
        // ...
    }
    
    template<typename T>
    void function(T param1, T param2){
        // ...
    }
    

    <class T>And <typename T>there is no difference.

    note! template<class/typename T>The declaration is only valid for the immediately following code block.

  • Call method

    • Automatic type inference

      int a; int b;
      
      function(a, b);
      // 没问题
      
      int a; char b;
      
      function(a, b);
      // 报错
      
    • Show specified type

      function<int>(a, b);
      

    note! You must explicitly specify the type when you do not pass parameters, see the following example.

    template<class T>
    void function();
    
    int main(){
          
          
        function();// 此时编译器无法自动推导,必须显式指定
    }
    
  • The difference between function templates and ordinary functions

    • Type check

      Template function type checking is stricter, and implicit conversion is not allowed. Examples:

      template<class T>
      T templateFun(T param1, T param2);
      
      int function2(int param1, int param2);
      
      int main(){
              
              
          int a; char b;
      	// 调用模板函数不允许隐式转换
          templateFun(a, c); // 报错
          
      	// 调用普通函数会发生隐式转换
          function2(a, c); // 没问题
      }
      

      However, rvalue passing parameters allow implicit conversion, for example:

      templateFun(1, 2); // 这是合法的
      
  • Call sequence

    When overloading, call ordinary functions first

    template<class T>
    T function(T param1, T param2);
    
    int function(int param1, int param2);
    
    int main(){
          
          
        int a; int b;
        function(a, b); // 报错
    }
    

    If you want to force a template function to be called, you can explicitly specify empty template parameters

    function<>(a, b);
    

    If the template function has better parameter matching, the template function will be called

    template<class T>
    T function(T param1, T param2);
    
    int function(int param1, int param2);
    
    int main(){
          
          
        char a; char b;
        // 模板函数拥有更少的隐式转换,所以这里会匹配模板函数
        function(a, b);
    }
    
  • Template functions allow overloading

    template<class T>
    T function(T param1, T param2);
    
    template<class T>
    T function(T param1, T param2, T param3);
    

Template implementation mechanism

  • Function templates generate different functions through specific types

  • Second compilation:

    First, check the syntax error of the function template and compile it. Then generate the corresponding template function and compile again.

Template reification

  • limitation

    Function templates have certain limitations,

    For example, arithmetic operations:

    For arrays, there is no such syntax as arr1 + arr2.

    If it is the object obj1 + obj2, you need to provide the corresponding overloaded function.

  • solve

    Reification of the function template:

    template<class T>
    void function(T a){
          
          
        // ... 模板实现
    }
    
    // 具体化
    template<> void function<Type>(Type& a){
          
          
        // ... 该模板函数的具体实现
    }
    

    That is, overloading for certain specific types.

Class template

  • Basic grammar

    template<class type1, class type2>
    class Type {
          
          
       private:
        type1 __a;
        type2 __b;
       public:
        Type(type1 a, type2 b);
    }
    

    note! Unlike function templates, you must explicitly specify the data type when instantiating an object.

    Type<int, char> obj(1, '2');
    
  • Default parameters

    The class template can use the default parameters of the type.

    template<class type1, class type2 = char>
    

    Of course, the function template can also use default parameters, but it's useless.

  • The rest is basically the same as the function template

Out-of-class implementation of class templates

Code:

template<class type1, class type2>
class Type {
    
    
   private:
    type1 __a;
    type2 __b;
   public:
    Type(type1 a, type2 b);
    void method(type1 a);
};

// 类外实现
template<class type1, class type2>
Type<type1, type2>::Type(type1 a, type2 b){
    
    
    // ...
}

template<class type1, class type2>
void Type<type1, type2>::method(type1 a){
    
    
    // ...
}

Sub-file preparation of class templates

The first thing to understand is that the method function of the class template will not be generated during the compilation phase, it is generated at runtime.

The general way we adjust the library is this:

#include"Type.h"
int main(){
    
    
    Type obj;
    obj.method();
}

An error will be reported, 无法解析的外部命令that is, the corresponding function cannot be called during the linking phase.

Because no specific class template method function has been created at this time, of course I can't find it.

You can do this at this time:

#include"Type.cpp"
int main(){
    
    
    Type obj;
    obj.method();
}

However, under normal circumstances, we generally do not do sub-class template file written statements and will achieve in one .hfile.

Class template instance as function parameter

The data type inside the template instance is uncertain. If you want to pass it as a parameter, you can specify it directly in the parameter list or define it as a function template.

  • Specified type

    Specify that only instances of this parameter type are allowed to be passed in:

    void function(Type<int, string> obj);
    
  • Template function

    Any instance of this template class is allowed to pass in:

    template<class T1, class T2>
    void function(Type<T1, T2> obj);
    
  • Completely abstract

    Needless to say, everyone knows this method:

    template<class T>
    void function(T obj);
    

Class templates and friends

  • In-class implementation

    note! Although it is implemented within a class, its scope is still global.

    template<class type1, class type2>
    class Type {
          
          
        friend void function(Type<type1, type2>& obj){
          
          
            // ...
        }
       private:
        type1 __a;
        type2 __b;
    };
    
  • Out-of-class implementation

    First look at the error implementation:

    template<class type1, class type2>
    class Type {
          
          
        friend void function(Type<type1, type2>& obj);
       private:
        type1 __a;
        type2 __b;
    };
    
    template<class type1, class type2>
    void function(Type<type1, type2>& obj){
          
          
            // ...
    }
    

    If the function is called at this time, an error will be reported 无法解析的命令, that is , the implementation of the function has not been found.

    Since the declaration inside the class is an ordinary function, and the implementation outside the class is a function template, when the parameter list is the same, the compiler will call the ordinary function first, which leads to the failure of the function implementation and link errors.

    Two methods:

    • Declare template function

      At this time, declare the friend declaration in the class as a template function.

      template<class type1, class type2>
      class Type {
              
              
          template<class type1, class type2>
          friend void function(Type<type1, type2>& obj);
         private:
          type1 __a;
          type2 __b;
      };
      
      template<class type1, class type2>
      void function(Type<type1, type2>& obj){
              
              
              // ...
      }
      
    • Function template reification

      Or first declare the template function, and then declare friends in the class, and make the parameters concrete.

      // 声明
      template<class type1, class type2> class Type<type1, type2>
      template<class type1, class type2> void function(Type<type1, type2>& obj);
      
      template<class type1, class type2>
      class Type {
              
              
          // 参数具体化声明
          friend void function<>(Type<type1, type2>& obj);
         private:
          type1 __a;
          type2 __b;
      };
      // 类外具体化实现
      template<class type1, class type2>
      void function(Type<type1, type2>& obj){
              
              
              // ...
      }
      

Inheritance in templates

Examples of errors:

No inheritance of abstract classes is allowed

template <class T>
class Base {
    
    };

// 继承
class Type : public Base {
    
    };

To inherit, it can be abstract or concrete.

  • Specify the template class to be inherited

    template <class T>
    class Base {
          
          };
    
    // 继承
    class Type : public Base<int> {
          
          };
    
  • Abstract designation

    template <class T>
    class Base {
          
          };
    
    // 继承
    template <class T>
    class Type : public Base<T> {
          
          };
    

Guess you like

Origin blog.csdn.net/qq_16181837/article/details/106678201