模板别名
在C++11中提供了模板别名。使用它可以方便的对一些具有不同类型参数的模板命名。例如有Matrix类模板:
template <typename T, int Line, int Col>
class Matrix{
....
};
为了可读性,我们增加2个特殊的矩阵:Square
和Vector
,分别表示行列相同的方阵和一维的向量。可以使用关键字using
声明类型别名:
template <typename T, int Line>
using Square = Matrix<T, Line, Line>; // (1)
template <typename T, int Line>
using Vector = Matrix<T, Line, 1>; // (2)
模板别名能为部分绑定的模板创建直观的名称,Square
和Vector
用起来十分方便且符合直觉。
Matrix<int, 5, 3> ma;
Square<double, 4> sq;
Vector<char, 5> vec;
模板别名还有一个典型的应用是Type-Traits库。
当使用std::move(arg)
时,编译器会使用std::remove_reference
来消除引用:
static_cast<std::remove_reference<decltype(arg)>::type&&>(arg); // (1)
static_cast<std::remove_reference_t<decltype(arg)>&&>(arg); // (2)
其中(2)使用模板别名:
template< class T >
using remove_reference_t = typename remove_reference<T>::type;
模板参数
模板参数可以是类型,非类型和模板。
类型
类型是最常用到的模板参数,例如:
std::vector<int> myVec;
std::map<std::string, int> myMap;
std::lock_guard<std::mutex> myLockGuard;
非类型
非类型可能如下:
- 左值引用
- nullptr
- 指针
- 枚举
- 整数值
整数值是最为常用的。例如std::array需要在编译时期指定其大小。
std::array<int, 3> myArray{1, 2, 3};
模板
模板也能作为模板的参数。
#include <iostream>
#include <list>
#include <vector>
#include <string>
template <typename T, template <typename, typename> class Cont > // (1)
class Matrix{
public:
explicit Matrix(std::initializer_list<T> inList): data(inList) { // (2)
for (auto d: data) std::cout << d << " ";
}
int getSize() const{
return data.size();
}
private:
Cont<T, std::allocator<T>> data; // (3)
};
int main(){
std::cout << '\n';
Matrix<int, std::vector> myIntVec{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; // (4)
std::cout << '\n';
std::cout << "myIntVec.getSize(): " << myIntVec.getSize() << '\n';
std::cout << std::endl;
Matrix<double, std::vector> myDoubleVec{1.1, 2.2, 3.3, 4.4, 5.5}; // (5)
std::cout << '\n';
std::cout << "myDoubleVec.getSize(): " << myDoubleVec.getSize() << '\n';
std::cout << '\n';
// (6)
Matrix<std::string, std::list> myStringList{"one", "two", "three", "four"};
std::cout << '\n';
std::cout << "myStringList.getSize(): " << myStringList.getSize() << '\n';
std::cout << '\n';
}
Matrix
有2个模板参数,第一个参数是元素的类型,第二个代表容器。其中第二个模板参数还是一个模板,它需要2个模板参数:第一个模板参数是容器中元素的类型,第二个参数是容器的空间分配器。
在Matrix中可以使用container< type of the elements, allocator of the elements>
形式的容器,例如:std::vector, std::deque, std::list。std::array 和 std::forward_list是不可用的,因为std::array需要一个整数值来指定其大小,而std::forward_list不支持size方法。