C++ [template advanced]

Table of contents

1. Some usage details of the template 

2. Non-type template parameters

3. Template specialization

4. Separate compilation of templates

Write at the end:


1. Some usage details of the template 

Let's go straight to the scene:

#include <iostream>
#include <vector>
#include <list>
using namespace std;

template<class Container>
void Print(const Container& v) {
	Container::const_iterator it = v.begin();
	while (it != v.end()) {
		cout << *it << " ";
		it++;
	}
	cout << endl;
}

void test1() {
	vector<int> v{ 1, 2, 3, 4 };
	list<int> lt{ 1, 2, 3, 4 };
	Print(lt);
}

int main()
{
	test1();

	return 0;
}

In this code, we have implemented a generic type, so that this Print has the ability to traverse various containers,

But this code will be reported by the compiler as an error:

The compiler told us very clearly here, telling us to add a typename in front of the const_iterator type

template<typename Container>
void Print(const Container& v) {
	typename Container::const_iterator it = v.begin();
	while (it != v.end()) {
		cout << *it << " ";
		it++;
	}
	cout << endl;
}

After adding it, it can indeed run through:

So why?

Because the compiler doesn't know whether your template parameter::const_iterator is a type or an object (type),

Here I can give an example:

class A {
public:
	static int const_iterator;
};

If there is such a class, you can use A::const_iterator,

So how does the compiler know how to instantiate it?

So you need to add a typename to tell the compiler that you are a type,

This way the compiler lets you through.

But there is actually a more convenient way to write:

template<typename Container>
void Print(const Container& v) {
	auto it = v.begin();
	while (it != v.end()) {
		cout << *it << " ";
		it++;
	}
	cout << endl;
}

Yes, welcome to the auto promotional video~, auto must be a type, so the compiler will not report an error.

In fact, we encountered such a scenario when we were learning priority queues:

The paragraph below him is the application scenario of typename.

When we use template parameters to take embedded types, we must use typename to remind the compiler that we are a type. 

2. Non-type template parameters

Let's go straight to the scene,

Say we want to implement a static stack:

Let the capacity of stack 1 be 10 and the capacity of stack 2 be 100, which obviously cannot be done.

#define N 10

template<class T>
class stack {
private:
	T _a[N];
	int _top;
};

void test2() {
	stack<int> st1;
	stack<int> st2;
}

At this time, we can use non-type template parameters to achieve: (yes, our previous ones were called type template parameters)

template<class T, size_t N>
class stack {
private:
	T _a[N];
	int _top;
};

void test2() {
	stack<int, 10> st1;
	stack<int, 100> st2;
}

In this way, the value can be controlled through the template.

3. Template specialization

Let's go straight to a scenario:

template<class T>
int Com(T a, T b) {
	return a > b;
}

// 模板的特化
template<>
int Com<int*>(int* a, int* b) {
	return *a > *b;
}

void test3() {
	int a = 1, b = 0;
	cout << Com(a, b) << endl;
	cout << Com(&a, &b) << endl;
}

If we want to perform different operations on a special situation,

We can use the technique of template specialization, since templates are instantiated based on the one that best matches.

However, in fact, in this case, we seem to be able to do it by overloading a function of type T*,

Then let's look at another example:

template<class T1, class T2>
class Date {
public:
	Date() { cout << "Date<T1, T2>" << endl; }
private:
	T1 _d1;
	T2 _d2;
};

void test4() {
	Date<int, int> d1;
	Date<int, double> d2;

output:

If I want to use different logic when using the <int, double> class template,

We can then use template specialization:

template<class T1, class T2>
class Date {
public:
	Date() { cout << "Date<T1, T2>" << endl; }
private:
};

template<>
class Date<int, double> {
public:
	Date() { cout << "Date<int, double>" << endl; }
private:
};

void test4() {
	Date<int, int> d1;
	Date<int, double> d2;
}

output:

We can see that by passing different template parameters, different logic can be followed.

Our above operation is full specialization, in fact, we can partial specialization, that is, partial specialization:

template<class T1, class T2>
class Date {
public:
	Date() { cout << "Date<T1, T2>" << endl; }
private:
};

template<class T1>
class Date<T1, double> {
public:
	Date() { cout << "Date<int, double>" << endl; }
private:
};

void test4() {
	Date<int, int> d1;
	Date<int, double> d2;
}

Such operations are also supported.

Partial specialization actually supports an operation that restricts certain types:

template<class T1, class T2>
class Date {
public:
	Date() { cout << "Date<T1, T2>" << endl; }
private:
};

template<class T1>
class Date<T1, double> {
public:
	Date() { cout << "Date<int, double>" << endl; }
private:
};

template<class T1, class T2>
class Date<T1*, T2*> {
public:
	Date() { cout << "Date<T1*, T2*>" << endl; }
private:
};

void test4() {
	Date<int, int> d1;
	Date<int, double> d2;
	Date<int*, double*> d3;
}

output:

 Like this case. 

4. Separate compilation of templates

Templates do not support separate compilation.

Consider this example:

Stack.h declares:

 Stack.cpp definition

 test.cpp calls:

 There is a link error:

In fact, the template has not been instantiated yet, causing the compiler to fail to find the definition when linking.

So is there any way to solve it?

The display instantiation operation can be performed here, so that it can be supported. 

But this method is not easy to use. If someone else passes a double type,

It is still very troublesome to write another operation that displays the instantiated double.

So if you use templates, it is recommended that if you have a large function,

The declaration and definition can be separated in the same file (one inside the class and one outside the class)

Write at the end:

The above is the content of this article, thank you for reading.

If you feel that you have gained something, you can give the blogger a like .

If there are omissions or mistakes in the content of the article, please private message the blogger or point it out in the comment area~

Guess you like

Origin blog.csdn.net/Locky136/article/details/131980631