第二章 类模板

1.一个简单的类模板代码

namespace Test {
	template<typename T>
	class Vector {
	public:
		void push_back(const T& t) {
			m_vector.push_back(t);
		}
		void pop() {
			m_vector.pop_back();
		}
		T const& top() {
			return m_vector.back();
		}
	private:
		std::vector<T> m_vector;
	};
}

注意:编译器在模板中的报错不一定实际上的错误!

分文件编写类模板
//A.hpp
template<typename T>
class A {
public:
	A() = default;
	A(const A<T>&);
	A const& operator=(const A<T>&);
	void func();
};
template<typename T>
A<T>::A(const A<T>& t) {
	std::cout << "构造函数" << std::endl;
}
template<typename T>
A<T>const& A<T>::operator=(const A<T>&) {
	std::cout << "operator =" << std::endl;
}
template<typename T>
void A<T>::func() {
	std::cout << "func" << std::endl;
}

3.std::type_triats提供很多接口

template<typename T>void B(const T&t) {
	if constexpr (std::is_default_constructible_v<T>) {
		std::cout << "有默认构造函数" << std::endl;
	}

};

4.模板特化

template<>
class A<std::string> {
	std::deque<std::string> m_deque;
public:
	A() = default;
	void func();
	void Lee();
	//A(const A<std::string>&);
	//A(A<std::string>&&);

};

//A<std::string>::A(const A&) {
//	std::cout << "拷贝构造函数" << std::endl;
//}
void A<std::string>::func() {
	std::cout << "fun" << std::endl;
}
void A<std::string>::Lee() {
	std::cout << "special" << std::endl;
}

5.部分特化

template<typename T>class A<T*>{
}

6.多参数特化

template<typename T1,typename T2>class B{

}
template<typename T>class B<T,T>{
}
template<typename T>class B<T,int>{
}
template<typename T1,typename T2>B<T1*,T2*>{
}

7.类模板默认参数

template<typename T, typename Cont = std::vector<T>>class B {
private:
	Cont elems;
public:
	void push_back(const T&t);
	void pop();
	const T& top() const;
};
template<typename T,typename Cont>
void B<T, Cont>::pop() {
	elems.pop_back();
}
template<typename T,typename Cont>
void B<T, Cont>::push_back(const T& t) {
	elems.push_back(t);
}
template<typename T,typename Cont>
const T& B<T, Cont>::top() const{
	return elems.back();
}

8.类型别名

typedef Stack<int> IntStack;
IntStack stack;

9.模板别名

template<typename T>
using C = B<T,std::deque<T>>;

10.类模板成员别名

template<typename Iterator>
struct Cap {
	using it = Cap<Iterator>;
	using It = typename Iterator*;

	Iterator a;
};
template<typename T>
using It = typename Cap<T>::it;
template<typename T>
using Ptr = typename  Cap<T>::It;

11.类模板推导

//Memeber memeber = 0;
//这里T被推导为int
template<typename T>
class Member {
public:
	Member(T t) :m_vector({ t }) {

	}
private:
	std::vector<T> m_vector;
};

12.类模板推导字符串

template<typename T>
class MString {
public:
	std::vector<T> m_vector;
public:
	MString(T t) :m_vector({ t }) {//这里会退化为char*
	
	}
	void push_back(const T&t){
		m_vector.push_back(t);
	}
};

13.推导指引

class MString {
public:
	std::vector<T> m_vector;
public:
	MString(T t) :m_vector({ t }) {
	
	}
	void push_back(const T&t){
		m_vector.push_back(t);
	}
};
//template<>
//class MString<std::string> {
//public:
//	MString(const char*) {
//		std::cout << "std::string 特化版本调用" << std::endl;
//	}
//
//};
MString(const char*)->MString<std::string>;

14.推到指引的实际作用模板化聚合

template<typename T>  struct Aggregates {
	T value;
	std::string id;
};
Aggregates(const char*,const char*)->Aggregates<std::string>;//这里这个指引起到构造函数的作用,使编译器能够推导模板类型(c++17后)