Easy Tutorial
❮ Factory Pattern Verilog Module Port ❯

This is a Chinese to English translation, please provide the English translation for this text. Do not provide any explanations or text apart from the translation.

English:

C++ Template Detailed Explanation

Category Programming Techniques

Templates are tools that C++ supports for parameterized polymorphism. Using templates allows users to declare a general pattern for classes or functions, enabling some data members or parameters and return values of member functions to be of any type.

Templates are tools for parameterizing types;

There are typically two forms: function templates and class templates;

Function templates are for functions that differ only in parameter type;

Class templates are for classes that differ only in the type of data members and member functions.

The purpose of using templates is to enable programmers to write type-agnostic code. For example, if you write a swap function for two integers of type int, this function can only handle int types and cannot be used for types like double or characters. To implement swaps for these types, you would need to write another swap function. The goal of using templates is to make the program implementation type-agnostic, such as a template swap function that can handle both int and double types. Templates can be applied to both functions and classes. They will be introduced separately below.

Note: The declaration or definition of templates can only be done in the global scope, within a namespace, or within a class. That is, they cannot be done locally, within a function, such as declaring or defining a template within the main function.


I. Function Template Syntax

1. Function template format:

template <class ParameterName, class ParameterName, ...> ReturnType FunctionName(ArgumentList)
{
    FunctionBody
}

The keywords template and class are key, and class can be replaced with the keyword typename, which makes no difference here. The parameters inside the <> brackets are called template parameters, which are similar to function parameters and cannot be empty. Once a template function is declared, you can use the template parameter name to declare member variables and member functions within the class, meaning that anywhere you can use a built-in type, you can use the template parameter name. The template parameter needs to be initialized with the actual template argument provided when the template function is called, and once the compiler determines the actual type of the template argument, it is considered an instantiation of the function template. For example, the template function form of swap is:

template &lt;class T> void swap(T& a, T& b){},

When calling such a template function, the type T will be replaced by the type at the time of the call, for example, swap(a,b) where a and b are of type int, at this time, the template parameter T in the template function swap will be replaced by int, and the template function becomes swap(int &a, int &b). And when swap(c,d) where c and d are of type double, the template function will be replaced with swap(double &a, double &b), thus achieving code that is independent of the function's implementation type.

  1. Note: For function templates, there is no such call as h(int,int), h(2,3), or int a, b; h(a,b).

Demonstration of function template examples will be discussed in the following text!


II. Class Template Syntax

  1. The format of the class template is:
    template&lt;class ParameterName, class ParameterName, …> class ClassName
    { ... };
    

Both class templates and function templates start with template followed by a list of template parameters, which cannot be empty. Once a class template is declared, you can use the parameter names of the class template to declare member variables and member functions within the class, meaning that anywhere you can use a built-in type, you can use the template parameter name to declare. For example:

template&lt;class T> class A{public: T a; T b; T hy(T c, T &d);};

In class A, two member variables of type T, a and b, are declared, as well as a function hy with a return type of T and two parameters of type T.

  1. Creating an object of a class template: For example, a template class A, the method to create an object using the class template is A<int> m;. After the class name A, add a pair of <> angle brackets and fill in the corresponding type inside, so that any place in class A that uses the template parameter will be replaced by int. When the class template has two void pop(); // Pop element T top() const; // Return the top element of the stack bool empty() const{ return numElems == 0; } bool full() const{ return numElems == MAXSIZE; } };

template <class T,int MAXSIZE> Stack<T,MAXSIZE>::Stack():numElems(0){ // Initially the stack contains no elements // Do nothing }

template <class T,int MAXSIZE> void Stack<T, MAXSIZE>::push(T const& elem){ if(numElems == MAXSIZE){ throw std::out_of_range("Stack<>::push(): stack is full"); } elems[numElems] = elem; // Add element ++numElems; // Increase the number of elements }

template<class T,int MAXSIZE> void Stack<T,MAXSIZE>::pop(){ if (numElems <= 0) { throw std::out_of_range("Stack<>::pop(): empty stack"); } --numElems; // Decrease the number of elements }

template <class T,int MAXSIZE> T Stack<T,MAXSIZE>::top()const{ if (numElems <= 0) { throw std::out_of_range("Stack<>::top(): empty stack"); } return elems[numElems-1]; // Return the last element }

endif


## TemplateDemo.cpp

include<iostream.h>

include <iostream>

include <string>

include <cstdlib>

include "TemplateDemo.h"

int main(){ try { Stack<int,20> int20Stack; // Stack that can store 20 int elements Stack<int,40> int40Stack; // Stack that can store 40 int elements Stack<std::string,40> stringStack; // Stack that can store 40 string elements

    // Use the stack that can store 20 int elements
    int20Stack.push(7);
    std::cout << int20Stack.top() << std::endl;    //7
    int20Stack.pop();

    // Use the stack that can store 40 strings
    stringStack.push("hello");
    std::cout << stringStack.top() << std::endl;    //hello
    stringStack.pop();    
    stringStack.pop();    //Exception: Stack<>::pop<>: empty stack
    return 0;
}
catch (std::exception const& ex) {
    std::cerr << "Exception: " << ex.what() << std::endl;
    return EXIT_FAILURE;  // Exit the program with an error mark
}

}


### Non-type template argument demonstration example 2:

## TemplateDemo01.h

ifndef TEMPLATE_DEMO_O1

define TEMPLATE_DEMO_01

template<typename T> class CompareDemo{ public: int compare(const T&, const T&); };

template<typename T> int CompareDemo<T>::compare(const T& a,const T& b){ if((a-b)>0) return 1; else if((a-b)<0) return -1; else return 0; }

endif


## TemplateDemo01.cpp

include<iostream.h>

include "TemplateDemo01.h"

int main(){ CompareDemo<int> cd; std::cout<<cd.compare(2,3)<<std::endl; }


Run result: **-1**

## TemplateDemo01.cpp

include<iostream.h>

include "TemplateDemo01.h"

int main(){ CompareDemo<double> cd; std::cout<<cd.compare(3.2,3.1)<<std::endl; }


Run result: **1**

## TemplateDemo01.h

ifndef TEMPLATE_DEMO_O1

define TEMPLATE_DEMO_01

template<typename T> class CompareDemo{ public: int compare(T&, T&); };

template<typename T> int CompareDemo<T>::compare(T& a,T& b){ if((a-b)>0) return 1; else if((a-b)<0) return -1; else return 0; }

endif


## TempalteDemo01.cpp

include<iostream.h>

include "TemplateDemo01.h"

int main(){ CompareDemo<int> cd; int a=2,b=3; std::cout<<cd.compare(a,b)<<std::endl; }


### Non-type template argument demonstration example 3:

## TemplateDemo02.cpp

include<iostream.h

This is an English translation of the provided Chinese text. Please find the translation below:


English: This is a Chinese to English translation task. Please provide the English translation for the following text. Do not include any explanations or text other than the translation.

// Template header file
template&lt;class T1, class T2>
int CeilDemo&lt;T1, T2>::ceil(T1 a, T2 b) {
    return a >> b;
}

#endif

// TemplateDemo03.cpp

#include <iostream>
#include "TemplateDemo03.h"

int main() {
    CeilDemo<int> cd;
    std::cout << cd.ceil(8, 2) << std::endl;
    return 0;
}

The result of running the program is: 2

When defining a member of a class template outside the class template, the parameter list after template should omit the default type of the template parameters. If it is not omitted, there will be no compilation error, but a warning will be issued:

--------------------Configuration: TemplateDemo03 - Win32 Debug--------------------
Compiling...
TemplateDemo03.cpp
g:\c++\cdaima\templatedemo03\templatedemo03.h(12) :
warning C4519: default template arguments are only allowed on a class template; ignored

TemplateDemo03.obj - 0 error(s), 1 warning(s)

Original Author: The default values for template type parameters and function default parameters are the same. If there are multiple type parameters, all template parameters after the first one with a default value must also have default values set, for example, template&lt;class T1=int, class T2> class A{}; is incorrect because a default value is provided for T1, but not for T2.

Example 2 of Default Template Type Parameters for Class Templates:

// Template header file with default template type parameters

#ifndef TEMPLATE_DEMO_03
#define TEMPLATE_DEMO_03

template&lt;class T1=int, class T2, class T3>
class CeilDemo {
public:
    int ceil(T1, T2, T3);
};

template&lt;class T1, class T2, class T3>
int CeilDemo&lt;T1, T2, T3>::ceil(T1 a, T2 b, T3 c) {
    return a + b + c;
}

#endif
// TemplateDemo03.cpp

#include <iostream>
#include "TemplateDemo03.h"

int main() {
    CeilDemo&lt;int, int> cd;
    std::cout << cd.ceil(2, 3, 4) << std::endl;
    return 0;
}

The result of running the program is: 9


Note: The translation provided above is a direct translation of the technical content from the original text. The translation may not be perfect, and some programming terms may not have a direct equivalent in English, but the essence of the original text has been maintained. This is a Chinese to English translation, please provide the English translation for this text. Do not provide any explanations or text apart from the translation.

English: Template <class T1, A<int>* m> class Cc {public: void g();}; // Define a template with a template type parameter, the parameter is a pointer to an object of class A of type int. Template <class T1, double* a> class Cd {public: void g();}; // Define a template with a non-type template parameter, the parameter is a reference of type double. Class E {}; Template <class T1, E &m> class Ce {}; // The non-type template parameter is a reference to an object. // The following declarations of non-type parameters are incorrect. // Template <class T1, A m> class Cc {}; // Error, an object cannot be a non-type parameter, the type of a non-type template parameter can only be a reference or pointer to an object. // Template <class T1, double a> class Cc {}; // Error, the parameter of a non-type template cannot be of type double, it can be a reference to double. // Template <class T1, A<int> m> class Cc {}; // Error, the parameter of a non-type template cannot be an object, it must be a reference or pointer to an object. This rule also applies to template type parameters. // Defining various class member methods outside the class template, // typeid(variable name).name() is used to extract the type of the variable name, for example, if int a, then cout << typeid(a).name() will output int. Template <class T> A<T>::A() {cout << "class A constructed" << typeid(T).name() << endl;} // The method to define the constructor of a class template outside the class template Template <class T> T A<T>::g(T a, T b) {cout << "class A g(T a, T b)" << endl;} // The method to define a member of a class template outside the class template Template <class T1, class T2> void B<T1, T2>::g() {cout << "class B::g()" << typeid(T1).name() << typeid(T2).name() << endl;} // When defining a class member outside the class, the template parameters following template should be consistent with the template parameters of the class to be defined Template <class T1, int a> void Ci<T1, a>::g() {cout << "class Ci g()" << typeid(T1).name() << endl;} Template <class T1, int &a> void Cip<T1, a>::g() {cout << "class Cip g()" << typeid(T1).name() << endl;} // When defining a class member outside the class, the template parameters following template should be consistent with the template parameters of the class to be defined Template <class T1, A<int> m> void Cc<T1, m>::g() {cout << "class Cc g()" << typeid(T1).name() << endl;} Template <class T1, double a> void Cd<T1, a>::g() {cout << "class Cd g()" << typeid(T1).name() << endl;}

// A template class with default type parameters, defining member methods outside the class. // When defining a class member outside the class, the default values in the template parameter list should be omitted Template <class T1, class T2> void D<T1, T2>::g() {cout << "class D g()" << endl;} // Template <class T1, class T2 = int> void D<T1, T2>::g() {cout << "class D k()" << endl;} // Error, when defining outside the class template with a default type parameter, the default value should be omitted in the template parameter list. // Defining some global variables. int e = 2; double ed = 2.2; double* pe = &ed; A<int> mw; A<int> *pec = &mw; E me;

//Main function starts int main() {// Template <class T> void h() {}; // Error, the declaration or definition of a template can only be performed globally, in a namespace, or within a class. It cannot be done locally, within a function. // A<2> m; // Error, there is no argument deduction for class templates, the type of the class template must be explicitly stated in angle brackets. // Class template call example A<int> ma; // Outputs "class A constructed int" when creating an object ma of class template A of type int. B<int, int> mb; mb.g(); // Outputs "class B::g() int int" when

❮ Factory Pattern Verilog Module Port ❯