📄 index.html
字号:
<td><font size="+1">
<pre>
template<typename T>
inline T Pair<T>::get_first() const
{
return first;
}
</pre>
</font>
</td>
</tr>
<tr>
<td valign="top"><font size="+1" color="#009999">Purpose:</font></td>
<td><font size="+1">Supply the implementation of a member function
for a class template.</font></td>
</tr>
</table>
</font>
</td>
</tr>
</table>
</font>
<hr><h2><font color="#009999">22.4 Template Linked List</font></h2>
<font size="+1">
<ul>
<li>Recall the linked list from chptr. 16</li>
<li><tt>List</tt> stored strings</li>
<li>Used the <tt>Node</tt> and <tt>Iterator</tt> classes</li>
<li>Let's make them into templates</li>
<li>Node:
<blockquote>
<pre>template<typename T>
class Node
{
public:
Node(T s);
private:
T data;
Node<T>* previous;
Node<T>* next;
};</pre>
</blockquote>
</li>
</ul>
</font>
<hr><h2><font color="#009999">22.4 Template Linked List (cont.)</font></h2>
<font size="+1">
<ul>
<li>List:
<blockquote>
<pre>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;
};</pre>
</blockquote>
</li>
</ul>
</font>
<hr><h2><font color="#009999">22.4 Template Linked List (cont.)</font></h2>
<font size="+1">
<ul>
<li>Turn <i>each</i> member function definition into a template:
<blockquote>
<pre>template<typename T>
Iterator<T> List<T>::begin()
{
Iterator<T> iter;
iter.position = first;
iter.last = last;
return iter;
}</pre>
</blockquote>
</li>
</ul>
</font>
<hr><h2><font color="#009999">Quality Tip 22.2</font></h2>
<font size="+1">
<hr color="#00ffff" size="6">
<p><font color="#009999">Use <tt>typedef</tt> to Form an Alias for a
Long Name</font></p>
<ul>
<li><tt>typedef</tt> long types:
<blockquote><tt>
typedef pair<int, double> ElementType;
<br>typedef vector< pair<string, <nobr>string> ></nobr>
StringMap;
</tt></blockquote>
</li>
<li>Space inside the <tt>> ></tt></li>
<li>Associates a new name with the given type</li>
<li>Use as any other type:
<blockquote><tt>
ElementType new_value; <font color="#0000cc">
// new_value is type pair<int, string></font>
</tt></blockquote>
</li>
</ul>
</font>
<hr><h2><font color="#009999">Quality Tip 22.2 (cont.)</font></h2>
<font size="+1">
<hr color="#00ffff" size="6">
<table border="1" cellpadding="4" bgcolor="#00cccc">
<tr>
<td bgcolor="#ffffff"><font size="+1"><font color="#009999">Syntax
<tt>typedef</tt> Statement</font>
<pre>typedef <i>declaration</i>;</pre>
<table border="0" cellpadding="4">
<tr>
<td valign="top"><font size="+1" color="#009999">
Example:</font></td>
<td><font size="+1">
<pre>typedef pair<int, string> ElementType;</pre>
</font>
</td>
</tr>
<tr>
<td valign="top"><font size="+1" color="#009999">Purpose:</font></td>
<td><font size="+1">Create an alias for a complicated type
name.</font></td>
</tr>
</table>
</font>
</td>
</tr>
</table>
</font>
<hr><h2><font color="#009999">22.5 Nontype Template Arguments</font></h2>
<font size="+1">
<ul>
<li>May be other things (integer constants)</li>
<li>Consider our matrix case study
<ul>
<li>3x3, at first</li>
<li>Then managed heap memory to remove this restriction</li>
<li>Template arguments provide a third alternative</li>
</ul>
</li>
</ul>
</font>
<hr><h2><font color="#009999">22.5 Nontype Template Arguments (cont.)
</font></h2>
<font size="+1">
<ul>
<li>Size could be specified by integer template arguments:
<blockquote>
<pre>template<typename T, int ROWS, int COLUMNS>
class Matrix
{
. . .
private:
T data[ROWS][COLUMNS];
};</pre>
</blockquote>
</li>
<li>Note, the integer values must be known at compile time</li>
</ul>
</font>
<hr><h2><font color="#009999">22.5 Nontype Template Arguments (cont.)
</font></h2>
<font size="+1">
<ul>
<li>Supply the type and the size:
<blockquote><tt>
Matrix<double, 3, 4> a; <font color="#0000cc">
// A 3 x 4 matrix of double values</font>
<br>Matrix<string, 2, 2> b;
</tt></blockquote>
</li>
<li>The bounds become part of the type</li>
</ul>
</font>
<hr><h2><font color="#009999">22.5 Nontype Template Arguments (cont.)
</font></h2>
<font size="+1">
<ul>
<li>Compatibility checked at compile time
<blockquote><tt>
Matrix<int, 3, 4> a;
<br>Matrix<double, 3, 4> b;
<br>Matrix<int, 5, 7> c;
<br>Matrix<int, 3, 4> d;
<br>b = a; <font color="#cc0000">
// Error, element types don't match.</font>
<br>c = a; <font color="#cc0000">
// Error, sizes dont match, so types differ.</font>
<br>d = a; <font color="#cc0000">
// OK. Element types and sizes match.</font>
</tt></blockquote>
</li>
<li>The requirements for matrix multiplication are much more difficult
to specify</li>
</ul>
</font>
<hr><h2><font color="#009999">22.6 Setting Behavior Using Template Arguments
</font></h2>
<font size="+1">
<ul>
<li>Specify behavior (set <i>policy</i>)</li>
<li>Generalize the <tt>max</tt> function to support types that:
<ul>
<li>Don't define <tt>operator<</tt></li>
<li>Have more than one way of ordering</li>
</ul>
</li>
<li>Make comparison a template argument:
<blockquote>
<pre>template<typename T, typename CMP>
T max(const T& left, const T& right, CMP cmp)
{
if (cmp(left, right))
return right;
return left;
}</pre>
</blockquote>
</li>
</ul>
</font>
<hr><h2><font color="#009999">22.6 Setting Behavior Using Template Arguments
</font></h2>
<font size="+1">
<ul>
<li><tt><</tt> has been replaced by a function call</li>
<li><tt>cmp</tt> may be either
<ol>
<li>An actual function</li>
<li>A function object (chptr. 17)</li>
</ol>
</li>
</ul>
</font>
<hr><h2><font color="#009999">22.6 Setting Behavior Using Template Arguments
(cont.)</font></h2>
<font size="+1">
<ul>
<li>E.g., use function objects to compare <tt>Employee</tt>s by salary or
name</li>
<li>Develop these two classes:
<blockquote>
<pre>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();
}</pre>
</blockquote>
</li>
</ul>
</font>
<hr><h2><font color="#009999">22.6 Setting Behavior Using Template Arguments
(cont.)</font></h2>
<font size="+1">
<blockquote>
<pre>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();
}</pre>
</blockquote>
</font>
<hr><h2><font color="#009999">22.6 Setting Behavior Using Template Arguments
(cont.)</font></h2>
<font size="+1">
<ul>
<li><tt>CompareByName</tt> and <tt>CompareBySalary</tt> are types</li>
<li>Represent two different orderings</li>
<li>We can use the <tt>max</tt> function in either sense:
<blockquote><tt>
Employee alice("Alice Smith", 45000);
<br>Employee fred("Fred Jones", 38500);
<br>
<br>Employee one = max(alice, fred, CompareBySalary());
<br>Employee two = max(alice, fred, CompareByName());
</tt></blockquote>
</li>
</ul>
</font>
<hr><h2><font color="#009999">22.6 Setting Behavior Using Template Arguments
(cont.)</font></h2>
<font size="+1">
<ul>
<li>Same idea applies to template class arguments</li>
<li>Maintaining a collection in sorted order
<ul>
<li>Specify the rules for comparing two elements</li>
<li>Do not specify criteria in the container itself</li>
</ul>
</li>
</ul>
</font>
<hr><h2><font color="#009999">22.6 Setting Behavior Using Template Arguments
(cont.)</font></h2>
<font size="+1">
<ul>
<li>Use template arguments:
<blockquote>
<pre>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;
};</pre>
</blockquote>
</li>
</ul>
</font>
<hr><h2><font color="#009999">22.6 Setting Behavior Using Template Arguments
(cont.)</font></h2>
<font size="+1">
<ul>
<li>The comparator is an attribute</li>
<blockquote>
<pre>template<typename T, typename CMP>
void OrderedCollection<T, CMP>::insert(T value)
{
iterator ptr = begin();
while (ptr != end())
{
if (comparator(value, *ptr))
{
<font color="#0000cc">// Found place to insert</font>
data.insert(ptr, value);
return;
}
++ptr;
}
// Insert at end
data.insert(ptr, value);
}</pre>
</blockquote>
</li>
</ul>
</font>
<hr><h2><font color="#009999">22.6 Setting Behavior Using Template Arguments
(cont.)</font></h2>
<font size="+1">
<ul>
<li>The collection is defined by the type it stores, and by the type
of its comparator
<blockquote><tt>
void f(OrderedCollection<Employee, CompareByName>& c)
<br>{
<br> . . .
<br>}
<br>
<br>OrderedCollection<Employee, CompareBySalary> a;
<br>a.add(. . .);
<br>OrderedCollection<Employee, CompareByName> b;
<br>b.add(. . .);
<br>f(a); <font color="#cc0000">// Errortypes don't match</font>
<br>f(b); <font color="#0000cc">// OK - type is OK</font>
</tt></blockquote>
</li>
</ul>
</font>
<hr><h2><font color="#009999">22.6 Setting Behavior Using Template Arguments
(cont.)</font></h2>
<font size="+1">
<ul>
<li>Identify a default policy</li>
<li>Associated with a template parameter</li>
<li>STL algorithms use the <tt>less<T></tt>, in
the <tt><functional></tt> header file</li>
<blockquote>
<pre>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;
}</pre>
</blockquote>
</li>
</ul>
</font>
<hr><h2><font color="#009999">22.6 Setting Behavior Using Template Arguments
(cont.)</font></h2>
<font size="+1">
<ul>
<li>The <tt>less</tt> defines a function object</li>
<li>Invokes <tt>operator<</tt></li>
<li>Specify <i>trait</i> as the default template argument
<blockquote><tt>
template<typename T, typename CMP = less<T> >
<br>class OrderedCollection
<br>{
<br> . . .
<br>}
</tt></blockquote>
</li>
<li>To use the default:
<blockquote><tt>
OrderedCollection<int> data; <font color="#0000cc">
// Will use the less than operator</font>
</tt></blockquote>
</li>
</ul>
</font>
<hr><h2><font color="#009999">22.7 Case Study: Matrices, Cont.</font></h2>
<font size="+1">
<ul>
<li>Create a template version of the <tt>Matrix</tt> class</li>
<li>Start with the class in chptr. 19
<ul>
<li>Avoids explaining interactions between templates and nested classes
</li>
<li>No reason to make the exception classes into templates</li>
</ul>
</li>
<li>Parameterize the element type only</li>
<li>Not the row and column bounds; simplifies overloading the arithmetic
operators</li>
<li>Zero is no longer an appropriate value for all types; remove the
initializer loop in the c'tor</li>
<li>Move member function definitions into the header file</li>
</ul>
</font>
<hr><h2><font color="#009999">22.7 Case Study: Matrices (<tt>matrix5.h</tt>)
</font></h2>
<font size="+1">
<script><!--
iframeWrapCode( "matrix5.h", "90%", "80%" )
//--></script>
</font>
<hr><h2><font color="#009999">22.7 Case Study: Matrices (<tt>matrix5.cpp</tt>)
</font></h2>
<font size="+1">
<script><!--
iframeWrapCode( "matrix5.cpp", "90%", "70%" )
//--></script>
</font>
<hr><h2><font color="#009999">22.7 Case Study: Matrices
(<tt>matrixtest5.cpp</tt>)</font></h2>
<font size="+1">
<script><!--
iframeWrapCode( "matrixtest5.cpp", "90%", "80%" )
//--></script>
</font>
<hr><h2><font color="#009999">Chapter Summary</font></h2>
<font size="+1">
<hr color="#00ffff" size="6">
<ol>
<li>A template allows a function or class to be parameterized by type</li>
<li>The template abstracts the actions to be performed</li>
<li>Template arguments are inferred from the values in a function invocation
</li>
<li>Template functions can have the same name as nontemplate functions. The
nontemplates are searched first for a match</li>
<li>Template classes allow the creation of containers that work with many
different types of values</li>
<li>Template classes must be explicitly instantiated in order to declare
new variables</li>
<li>Template arguments can be type names or they can be constants</li>
<li>A <tt>typedef</tt> statement can be used to form an alias for a type
name</li>
<li>Template arguments can be used to set behavior, for example, setting the
comparison algorithm for sorted containers</li>
</ol>
</font>
</body>
</html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -