1- Class Templates
Review: Function Templates
- A function template is not a type, to a function, or any other entity
- No code is generated from a source file that contains only template definitions
- The template arguments must be determined, then the compiler can generate an actual function
- "Function Template" vs "Template Function"
cpp
template<typename T>
T sum(T x, T y)
{
cout << "The input type is " << typeid(T).name() << endl;
return x + y;
}
// instantiates sum<double>(double, double)
template double sum<double> (double, double);
// instantiates sum<char> (char, char), template argument deduced
template char sum<> (char, char);
// instantiates sum<int>(int, int), template argument deduced
template int sum(int, int);
模版函数是函数模版生成实例化后的具体的函数
- Implicit instantiation occurs when a function template is not explicitly instantiated
cpp
template<typename T>
T sum(T x, T y)
{
cout << "The input type is " << typeid(T).name() << endl;
return x + y;
}
// Implicitlyy instantiates product<int>(int, int)
cout << "product = " << product<int>(2.2f, 3.0f) << endl;
// Implicitly instantiates product<float>(float, float)
cout << "product = " << product(2.2f, 3.0f) << endl;
Different Classes for Different Type Matrices
- Matrix with
int
elements, Matrix withfloat
elements
matchless.cpp
cpp
#include <iostream>
using namespace std;
// Class IntMat
class IntMat
{
size_t rows;
size_t cols;
int * data;
public:
IntMat(size_t rows, size_t cols):
rows(rows), cols(cols)
{
data = new int[rows * cols]{};
}
~IntMat()
{
delete [] data;
}
IntMat(const IntMat&) = delete;
IntMat& operator=(const IntMat&) = delete;
int getElement(size_t r, size_t c);
bool setElement(size_t r, size_t c, int value);
};
int IntMat::getElement(size_t r, size_t c)
{
if ( r >= this->rows || c >= this->cols)
{
cerr << "Indices are out of range" << endl;
return 0;
}
return data[ this->cols * r + c];
}
bool IntMat::setElement(size_t r, size_t c, int value)
{
if ( r >= this->rows || c >= this->cols)
return false;
data[ this->cols * r + c] = value;
return true;
}
// Class FloatMat
class FloatMat
{
size_t rows;
size_t cols;
float * data;
public:
FloatMat(size_t rows, size_t cols):
rows(rows), cols(cols)
{
data = new float[rows * cols]{};
}
~FloatMat()
{
delete [] data;
}
FloatMat(const FloatMat&) = delete;
FloatMat& operator=(const FloatMat&) = delete;
float getElement(size_t r, size_t c);
bool setElement(size_t r, size_t c, float value);
};
float FloatMat::getElement(size_t r, size_t c)
{
if ( r >= this->rows || c >= this->cols)
{
cerr << "getElement(): Indices are out of range" << endl;
return 0.f;
}
return data[ this->cols * r + c];
}
bool FloatMat::setElement(size_t r, size_t c, float value)
{
if ( r >= this->rows || c >= this->cols)
{
cerr << "setElement(): Indices are out of range" << endl;
return false;
}
data[ this->cols * r + c] = value;
return true;
}
int main()
{
IntMat imat(3,4);
imat.setElement(1, 2, 256);
FloatMat fmat(2,3);
fmat.setElement(1, 2, 3.14159f);
// FloatMat fmat2(fmat); //error
// FloatMat fmat3(2,3);
// fmat3 = fmat; //error
cout << imat.getElement(1,2) << endl;
cout << fmat.getElement(1,2) << endl;
return 0;
}
bash
256
3.14159
Class Templates
- A class template defines a family of classes
mat template.cpp
cpp
#include <iostream>
using namespace std;
// Class Template
template<typename T>
class Mat
{
size_t rows;
size_t cols;
T * data;
public:
Mat(size_t rows, size_t cols): rows(rows), cols(cols)
{
data = new T[rows * cols]{};
}
~Mat()
{
delete [] data;
}
Mat(const Mat&) = delete;
Mat& operator=(const Mat&) = delete;
T getElement(size_t r, size_t c);
bool setElement(size_t r, size_t c, T value);
};
template <typename T>
T Mat<T>::getElement(size_t r, size_t c)
{
if ( r >= this->rows || c >= this->cols)
{
cerr << "getElement(): Indices are out of range" << endl;
return 0;
}
return data[ this->cols * r + c];
}
template <typename T>
bool Mat<T>::setElement(size_t r, size_t c, T value)
{
if ( r >= this->rows || c >= this->cols)
{
cerr << "setElement(): Indices are out of range" << endl;
return false;
}
data[ this->cols * r + c] = value;
return true;
}
template class Mat<int>; // Explicitly instantiate template Mat<int>
//template Mat<float> and Mat<double> will be instantiate implicitly
int main()
{
Mat<int> imat(3,4);
imat.setElement(1, 2, 256);
Mat<float> fmat(2,3);
fmat.setElement(1, 2, 3.14159f);
Mat<double> dmat(2,3);
dmat.setElement(1, 2, 2.718281828);
// Mat<float> fmat2(fmat); //error
// Mat<float> fmat3(2,3);
// fmat3 = fmat; //error
cout << imat.getElement(1,2) << endl;
cout << fmat.getElement(1,2) << endl;
cout << dmat.getElement(1,2) << endl;
return 0;
}
bash
256
3.14159
2.71828
2- Template Non-Type Parameters
Non-Type Parameters
- To declare a template
cpp
template <parameter-list> declareation
- The parameters can be
(1) type tamplate parameters
(2) template template parameters
(3) non-type template parameters
integral types, floating-point type, pointer types, Value reference types
cpp
vector<int> vec1;
vector<int, 16> vec2;
- If we want to create a static matrix(no dynamic memory allocation inside)
cpp
// Class Template
template<typename T, size_t rows, size_t cols>
class Mat
{
T data[rows][cols];
public:
Mat(){}
T getElement(size_t r, size_t c);
bool setElement(size_t r, size_t c, T value);
};
cpp
Mat<int> vec1(3, 3);
Mat<int, 3, 3> vec2;
nontypeparam.cpp
cpp
#include <iostream>
using namespace std;
// Class Template
template<typename T, size_t rows, size_t cols>
class Mat
{
T data[rows][cols];
public:
Mat(){}
the default copy constructor will copy each element of a static array member
so we do not 'delete' the copy constructor
the same with the assignment operator
// Mat(const Mat&) = delete;
// Mat& operator=(const Mat&) = delete;
T getElement(size_t r, size_t c);
bool setElement(size_t r, size_t c, T value);
};
template<typename T, size_t rows, size_t cols>
T Mat<T, rows, cols>::getElement(size_t r, size_t c)
{
if ( r >= rows || c >= cols)
{
cerr << "getElement(): indices are out of range" << endl;
return 0;
}
return data[r][c];
}
template<typename T, size_t rows, size_t cols>
bool Mat<T, rows, cols>::setElement(size_t r, size_t c, T value)
{
if ( r >= rows || c >= cols)
{
cerr << "setElement(): Indices are out of range" << endl;
return false;
}
data[r][c] = value;
return true;
}
template class Mat<int, 2, 2>; // Explicitly instantiate template Mat<int, 2, 2>
typedef Mat<int, 2, 2> Mat22i;
//template Mat<float, 3, 1> will be instantiate implicitly
int main()
{
Mat22i mat;
mat.setElement(2, 3, 256);
cout << mat.getElement(2, 3) << endl;
mat.setElement(1, 1, 256);
cout << mat.getElement(1, 1) << endl;
Mat<float, 3, 1> vec;
vec.setElement(2, 0, 3.14159f);
cout << vec.getElement(2, 0) << endl;
Mat<float, 3, 1> vec2(vec);
cout << vec2.getElement(2, 0) << endl;
// vec2 = mat; //error
return 0;
}
bash
setElement(): Indices are out of range
getElement(): indices are out of range
0
256
3.14159
3.14159
Template in OpenCV
- 模版的继承
将父类的第三个元素锁定为1
3- Class Template Specialization
Class template specialization
- The class template can be for most types
- But we want to save memory for type
bool
(1 byte or 1bit)
cpp
template<typename T>
class MyVector
{
size_t length;
T * data;
public:
MyVector(size_t length): length(length)
{
data = new T[length]{};
}
~MyVector()
{
delete [] data;
}
MyVector(const MyVector&) = delete;
MyVector& operator=(const MyVector&) = delete;
T getElement(size_t index);
bool setElement(size_t index, T value);
};
- Specialize
MyVector
forbool
cpp
template<>
class MyVector<bool>
{
size_t length;
unsigned char * data;
public:
MyVector(size_t length): length(length)
{
int num_bytes = (length - 1) / 8 + 1;
data = new unsigned char[num_bytes]{};
}
~MyVector()
{
delete [] data;
}
MyVector(const MyVector&) = delete;
MyVector& operator=(const MyVector&) = delete;
bool getElement(size_t index);
bool setElement(size_t index, bool value);
};
Example
specialization.cpp
cpp
#include <iostream>
using namespace std;
// Class Template
template<typename T>
class MyVector
{
size_t length;
T * data;
public:
MyVector(size_t length): length(length)
{
data = new T[length]{};
}
~MyVector()
{
delete [] data;
}
MyVector(const MyVector&) = delete;
MyVector& operator=(const MyVector&) = delete;
T getElement(size_t index);
bool setElement(size_t index, T value);
};
template <typename T>
T MyVector<T>::getElement(size_t index)
{
if (index >= this->length)
{
cerr << "getElement(): Indices are out of range" << endl;
return 0;
}
return data[index];
}
template <typename T>
bool MyVector<T>::setElement(size_t index, T value)
{
if (index >= this->length)
{
cerr << "setElement(): Indices are out of range" << endl;
return false;
}
data[ index ] = value;
return true;
}
template class MyVector<int>; // Explicitly instantiate template Mat<int>
// class specialization
template<>
class MyVector<bool>
{
size_t length;
unsigned char * data;
public:
MyVector(size_t length): length(length)
{
int num_bytes = (length - 1) / 8 + 1;
data = new unsigned char[num_bytes]{};
}
~MyVector()
{
delete [] data;
}
MyVector(const MyVector&) = delete;
MyVector& operator=(const MyVector&) = delete;
bool getElement(size_t index);
bool setElement(size_t index, bool value);
};
bool MyVector<bool>::getElement(size_t index)
{
if (index >= this->length)
{
cerr << "getElement(): Indices are out of range" << endl;
return 0;
}
size_t byte_id = index / 8;
size_t bit_id = index % 8;
unsigned char mask = (1 << bit_id);
return bool(data[byte_id] & mask) ;
}
bool MyVector<bool>::setElement(size_t index, bool value)
{
if (index >= this->length)
{
cerr << "setElement(): Indices are out of range" << endl;
return false;
}
size_t byte_id = index / 8;
size_t bit_id = index % 8;
unsigned char mask = (1 << bit_id);
if (value)
data[byte_id] |= mask;
else
data[byte_id] &= ~mask;
return true;
}
int main()
{
MyVector<int> vec(16);
vec.setElement(3, 256);
cout << vec.getElement(3) << endl;
MyVector<bool> boolvec(17);
boolvec.setElement(15, false);
boolvec.setElement(16, true);
cout << boolvec.getElement(15) << endl;
cout << boolvec.getElement(16) << endl;
return 0;
}
bash
256
0
1
4-std
Class
std::basic_string
- Store and manipulate sequences of char-like objects
std::array
- a container that encapsulates fixed size arrays
cpp
template<
class T,
std::size_t N
>struct array;
std::array<int, 3>a2 = {1,2,3};
Some other templates
- vector
cpp
template<
class T,
class Allocator = std::allocator<T>
>class vector;
- list
cpp
template<
class T,
class Allocator = std::allocator<T>
>class list;
- set
cpp
template<
class Key,
class Compare = std::less<Key>,
class Allocator = std::allocator<Key>
>class set
- map
cpp
template<
class Key,
class T,
class Compare = std::less<Key>,
class Allocator = std::allocator<std::pair<const Key, T>>
>>class map;
- stack
cpp
template<
class T,
class Container = std::deque<T>
>class stack;