C++ Function Template and Class Template

Keywords: C++

0.Summary:

Templates are the basis of generic programming, which writes code in a way that is independent of any particular type.

Templates are blueprints or formulas for creating generics or functions. Containers, iterators, algorithms, and so on, are examples of generic programming.

In C++, templates are divided into function and class templates.

1.Function template:

Function templates are not real functions for which the compiler cannot generate executable code.

Defining a function template is just a description of the parameter functional framework, and when it is executed, its functionality is determined by the actual parameters passed.

When a compiler automatically generates a function from a template, all type parameters in the template are replaced with the specific type name, while the rest are left intact.
The same type parameter can only be replaced by the same type. When compiled into a statement calling a function template, the compiler infers how to replace the type parameter in the template based on the type of the argument.

Definition:

template <typename Type parameter 1, typename Type parameter 2, ...>
Return value type function name(parameter list) 
{
	Function Body
}

Among them, type parameter is the placeholder name of the data type used by the function, and type parameter placeholders can be used in return value type, parameter list, and function body.

The process by which a compiler automatically generates functions from templates is called "instantiation of templates". Functions resulting from instantiation of templates are called template functions.

In some compilers, templates are checked for syntax correctness only when they are instantiated. If a template is written in a program but not used, the compiler will not report a syntax error in the template.

When instantiating a template, the compiler does not have to instantiate the type parameters in the template only by calling the arguments of the statement, which explicitly indicates what type to instantiate.
The method is:

Template Name<Actual type parameter 1, Actual type parameter 2, ...>

Give an example:

//Define a function template: A function used to compare two-digit sizes, regardless of type:
template <typename T>
inline T const& Max(T const& a, T const& b) 
{
	return a < b ? b : a;
}

//Instantiation of a function template:
int main() {
	int a = 4, b = 5;
    int c = Max(a, b);
    cout << c << endl;

	double x = 8.1, double y = 1.8;
	double z = Max(x, y);
	cout << z << endl;

	//Template invocation statements clearly indicate what type of type parameter to instantiate:
	float f = Max<float>(7.7, 6,6);
	cout << f << endl;
}

Summary:

There are two ways to instantiate a function template:

  1. Instantiate the type parameter in the template by calling the argument of the statement;
  2. Explicitly specify which type parameter to instantiate in the template call statement.

1.1 Practical application of function templates in IM projects:

//Define function templates:
//The function initiates a connection active connection to all servers in the *server_list list chain and saves the connection information to the server_list.
//Each connection corresponds to a local instance of type T, and templates can be reused on multiple server s of different types:
template <typename T> 
void serv_init(serv_info_t* server_list, uint32_t server_count)
{
	for(uint32_t i = 0; i < server_count; i++) {
		T* pConn = new T();
		pConn->Connect(serv_list[i].server_ip.c_str(), server_list[i]);
		server_list[i].serv_conn = pConn;
		server_list[i].idle_cnt = 0;
		server_list[i].reconnect_cnt = MIN_RECONNECT_CNT / 2;
	}
}


//Instantiate a function template:
serv_init<CDBServConn>(g_db_server_list, g_db_server_count);

serv_init<CRouteServConn>(g_route_server_list, g_route_server_count);


2.Class template:

When there are two or more classes that have the same functionality but only different data types, you can use class templates for code reuse.

Definition:

//Class template declaration:
template <typename Type parameter 1, typename Type parameter 2, ...>
Class declaration

//Class template definition:
template <typename Type parameter 1, typename Type parameter 2, ...>
class Class name
{
public:
	Class member function
private:
	Class members
};

Give an example:

template <typename T>
class A 
{
public:
	A(T t) {
		this->t = t;
	}
	T& getT() {
		return t;
	}
private:
	T t;
};

int main() {
	A<int> a(100);
	a.getT();
    return 0;
}

2.1 Inheritance class template syntax:

When a subclass inherits from a template class (the parent is a template class), you need to let the compiler know what the specific data type of the parent class is (essentially, to let the compiler know how much memory space it takes).

For example:

//Define a template class as parent:
template <typename T>
class A 
{
public:
	A(T x) { t = x; }
	void out() { cout << t << endl; }
private:
	T t;
};


//A subclass that inherits a template class:
//You must let the compiler know the specific data type of the parent class:
class B : public A<int> {
public:
	B(int a, double x) : A<int>(a) { y = x; }
	void out() { A<int>::out(); cout << y << endl; }
private:
	double y;
}

static keywords in type 2.2 templates:

Key points:

  1. Static static members of the same type of class template are shared by all class objects, consistent with normal classes;
  2. Because the compiler compiles templates in a "secondary compilation" fashion, when class templates are initialized to multiple instance types, multiple static members of the corresponding different types also occur.

_When a static member modified by static appears in a class template, we can only use it as we normally understand it. Static modifies the members of a class to be static, so-called static class members refer to the members of a class at the class level, which can be used without instantiating an object.And all objects share the same static class member because the static members of the class belong to the class and not to the object.

_Then, the implementation mechanism of class templates is through the principle of "second compilation".
Instead of compiling all the possible types into their respective classes the first time a class template is compiled by the C++ compiler (it is also not possible, there are too many built-in data types in C++), it compiles part of the first compilation and does not replace generics with specific types when it encounters them (at which point the compiler does not know the specific types yet).Instead, replace the generic with the specific type at the second compilation (when the compiler already knows what specific types are instantiated in the program by the first compilation).

_Because of the principle of "secondary compilation" of class templates plus members modified by the static keyword, when they are together a class template is actually compiled into several specific types of classes, the corresponding static members of different types of class templates are also different (belonging to different classes), but the static members of the same type of class templates are shared.(belongs to the same class).


2.3 Actual application of class templates in IM projects:

//Template class for the singleton pattern:
//The constructor of the class is encapsulated as private, and the Instance() member function is used to obtain an instance:
template <typename T>
class Singleton {
public:
	static T& Instance() {
		if(Singleton::s_instance == 0) {
			Singleton::s_instance = CreateInstance();
			return *(Singleton::s_instance);
		}
	}
private:
	static T* s_instance;	
private:
	static T* CreateInstance() {
		return new T();
	}
};


//Instantiate Singleton Template Class
class TransferTaskManager : public Singleton<TransferTaskManager> 
{
public:
	~TransferTaskManager();
private:
	TransferTaskManager();
}

3. The difference between keyword typename and class:

The keyword class acts exactly like typename in the template syntax.

After the introduction of C++ into templates, templates are initially defined by:
template<class T>......
Here the class keyword indicates that T is a type, and later to avoid confusion about the use of class in these two places, the typename keyword was introduced, which serves the same purpose as class to indicate that the following symbol is a type, so that the following can be used when defining a template:
template<typename T>......


Reference:
https://debuger.blog.csdn.net/article/details/94622335

Posted by surajkandukuri on Fri, 15 Oct 2021 09:16:11 -0700