void print(ostream& out, int data[], int count)
{
out << "[";
for (int i = 0; i < count; i++)
{
if (i > 0)
out << ",";
out << data[i];
}
out << "]";
}
template<typename T>
void print(ostream& out, T data[], int count)
{
out << "[";
for (int i = 0; i < count; i++)
{
if (i > 0)
out << ",";
out << data[i];
}
out << "]";
}
Syntax 22.1:
Template Function Definition
template<typename type_var1, ..., typename type_varn>
return_type function_name(parameters)
{
statements
}
|
Syntax 22.1:
Template Function Definition (cont.)
|
int a[] = {2, 4, 5};
print(cout, a, 3); // Will use int print
double b[] = {3.14159, 2.7};
print(cout, b, 2); // Will use double print
string c[] = {"Fred", "Sally", "Alice"};
print(cout, c, 3); // Will use string print
A type argument is characterized implicitly, by its use in the function.
template<typename T>
T max(const T& left, const T& right)
{
if (left < right)
return right;
return left;
}
Employee mary("Mary Smith", 25000);
Employee fred("Fred Jones", 37500);
Employee big = max(mary, fred); // Error - invalid types
Coercion doesn't happen. You can't mix types.
double e = max( 2, 3.13 ); // Error - cannot infer type argument
double e = max<double>( 2, 3.13 ); // OK - integer will be converted to a double
Pair minmax(vector<int> v)
{
int min = v[0];
int max = v[0];
for (int i = 1; i < v.size(); i++)
{
if (v[i] < min) min = v[i];
if (v[i] > max) max = v[i];
}
return Pair(min, max);
}
Pair p = minmax(data);
cout<< p.get_first() << " "<< p.get_second() << "\n";
Example: non-template class:
class Pair
{
public:
Pair(int a, int b);
int get_first() const;
int get_second() const;
private:
int first;
int second;
};
inline Pair::Pair(int a, int b)
{
first = a;
second = b;
}
inline int Pair::get_first() const
{
return first;
}
inline int Pair::get_second() const
{
return second;
}
Pair<int, int>
Pair<string, int>
template<typename F, typename S>
class Pair
{
public:
Pair(const F& a, const S& b);
F get_first() const;
S get_second() const;
private:
F first;
S second;
};
template<typename F, typename S>
inline Pair<F, S>::Pair(const F& a, const S& b)
{
first = a;
second = b;
}
template<typename F, typename S>
inline F Pair<F, S>::get_first() const
{
return first;
}
template<typename F, typename S>
inline S Pair<F, S>::get_second() const
{
return second;
}
Syntax 22.2
Template Class Definition
template<typename type_var1, ..., typename type_varn>
class ClassName
{
features
};
|
Syntax 22.2
Template Class Definition (cont.)
|
Syntax 22.3:
Template Member Function Definition
template<typename type_variable>
{
statements
}
|
template<typename T>
class Node
{
public:
Node(T s);
private:
T data;
Node<T>* previous;
Node<T>* next;
};
template<typename T>
class List
{
public:
List();
void push_back(T s);
void insert(Iterator<T> pos, T s);
Iterator<T> erase(Iterator<T> pos);
Iterator<T> begin();
Iterator<T> end();
private:
Node<T>* first;
Node<T>* last;
};
template<typename T>
Iterator<T> List<T>::begin()
{
Iterator<T> iter;
iter.position = first;
iter.last = last;
return iter;
}
Use typedef to Form an Alias for a Long Name
typedef pair<int, double> ElementType;
typedef vector< pair<string,string> > StringMap;
ElementType new_value; // new_value is type pair<int, string>
Syntax
typedef Statement
typedef declaration;
|
template<typename T, int ROWS, int COLUMNS>
class Matrix
{
. . .
private:
T data[ROWS][COLUMNS];
};
Matrix<double, 3, 4> a; // A 3 x 4 matrix of double values
Matrix<string, 2, 2> b;
Matrix<int, 3, 4> a;
Matrix<double, 3, 4> b;
Matrix<int, 5, 7> c;
Matrix<int, 3, 4> d;
b = a; // Error, element types don't match.
c = a; // Error, sizes dont match, so types differ.
d = a; // OK. Element types and sizes match.
template<typename T, typename CMP>
T max(const T& left, const T& right, CMP cmp)
{
if (cmp(left, right))
return right;
return left;
}
class CompareBySalary
{
public:
bool operator()(const Employee& a,
const Employee& b) const;
};
bool CompareBySalary::operator()(const Employee& a,
const Employee& b) const
{
return a.get_salary() < b.get_salary();
}
class CompareByName
{
public:
bool operator()(const Employee& a,
const Employee& b) const;
};
bool CompareByName::operator()(const Employee& a,
const Employee& b) const
{
return a.get_name() < b.get_name();
}
Employee alice("Alice Smith", 45000);
Employee fred("Fred Jones", 38500);
Employee one = max(alice, fred, CompareBySalary());
Employee two = max(alice, fred, CompareByName());
template<typename T, typename CMP>
class OrderedCollection
{
public:
typedef Iterator<T> iterator;
void add(T value);
iterator begin();
iterator end();
private:
List<T> data;
CMP comparator;
};
template<typename T, typename CMP>
void OrderedCollection<T, CMP>::insert(T value)
{
iterator ptr = begin();
while (ptr != end())
{
if (comparator(value, *ptr))
{
// Found place to insert
data.insert(ptr, value);
return;
}
++ptr;
}
// Insert at end
data.insert(ptr, value);
}
void f(OrderedCollection<Employee, CompareByName>& c)
{
. . .
}
OrderedCollection<Employee, CompareBySalary> a;
a.add(. . .);
OrderedCollection<Employee, CompareByName> b;
b.add(. . .);
f(a); // Errortypes don't match
f(b); // OK - type is OK
template<typename T>
class less
{
bool operator()(const T& x, const T& y) const;
}
template<typename T>
bool less<T>::operator()(const T& x, const T& y) const
{
return x < y;
}
template<typename T, typename CMP = less<T> >
class OrderedCollection
{
. . .
}
OrderedCollection<int> data; // Will use the less than operator