[ Pobierz całość w formacie PDF ]

provides an alternative definition of the primary template. It is used instead of the
primary definition when the arguments in any specialization match those that are given in
the partial specialization. For instance, a partial specialization of Vector can handle
pointer types exclusively. Thus, for specializations of fundamental types and user-defined
types, the primary Vector class is used. For pointers, the partial specialization is used
instead of the primary class template. A pointer partial specialization can optimize the
manipulation of pointers in several ways.
In addition, some operations that manipulate pointers involve dereferencing and the use
of operator ->, neither of which is used with non-pointer types.
A partial specialization is defined as follows:
//filename: Vector.hpp
template class Vector //partial specialization of Vector
{
private:
size_t size;
void * p;
public:
Vector();
~Vector();
//...member functions
size_t size() const;
};
//Vector.hpp
A partial specialization is indicated by the parameter list that immediately follows the
class template name (remember that the primary template is declared without the list after
its name). Compare these two forms:
template class Vector //primary template
{};
template class Vector //partial specialization
{};
Partial specializations of a class template that has several parameters are declared as
follows:
template class A { }; // primary
template class A { }; // partial
specialization
template class A { }; // another partial
specialization
Partial specializations must appear after the primary declaration of a
class template, and its parameter cannot contain default types.
Explicit Specialization of a Class Template
An explicit specialization of a class template provides an alternative definition of the
primary template. It is used instead of the primary definition if the arguments in a
particular specialization match those that are given in the explicit specialization. When is
it useful? Consider the Vector template: The code that is generated by the compiler for
the specialization Vector is very inefficient. Instead of storing every Boolean
value in a single bit, it occupies at least an entire byte. When you are manipulating large
amounts of bits, for example in logical operations or digital signal processing, this is
unacceptable. In addition, bit-oriented operations can be performed more efficiently using
the bitwise operators. Obviously, there are significant advantages to defining a Vector
template that is specifically adjusted to manipulate bits. Following is an example of an
explicit specialization Vector that manipulates bits rather than bytes:
template class Vector //explicit specialization
{
private:
size_t sz;
unsigned char * buff;
public:
explicit Vector(size_t s = 1) : sz(s),
buff (new unsigned char [(sz+7U)/8U] ) {}
Vector (const Vector & v);
Vector& operator= (const Vector& v);
~Vector();
//other member functions
bool& operator [] (unsigned int index);
const bool& operator [] (unsigned int index) const;
size_t size() const;
};
void bitmanip()
{
Vector bits(8);
bits[0] = true; //assign
bool seventh = bits[7]; //retrieve
}
The template prefix indicates an explicit specialization of a primary template. The
template arguments for a specialization are specified in the angular brackets that
immediately follow the class name. The specialization hierarchy of Vector that has been
defined thus far is as follows:
template class Vector //primary template
{};
template class Vector //partial specialization
{};
template class Vector //explicit specialization
{};
Fortunately, the Standard Template Library already defines a specialization of
std::vector for manipulating bits optimally, as you will read in the next chapter,
"STL and Generic Programming."
Specializations of Class Template Functions
The overloaded operator == of class Vector performs a plausible comparison between
two Vector objects when their elements are either fundamental types or objects that
overload operator ==. However, a comparison of two objects that store C strings is likely
to yield the wrong result. For example
#include "Vector.hpp"
extern const char msg1[] = "hello";
extern const char msg2[] = "hello";
int main()
{
Vector v1(1), v2(1); //the same number of elements
v1[0] = msg1;
v2[0] = msg2;
bool equal = (v1 == v2); //false, strings are equal but pointers
aren't
return 0;
}
NOTE: Whether identical string literals are treated as distinct objects is
implementation-dependent. Some implementations might store the
constants msg1 and msg2 at the same memory address (on such
implementations, the expression bool equal = (v1 == v2); yields
true). However, the discussion here assumes that msg1 and msg2 are stored
in two distinct memory addresses.
Although v1 and v2 have the same number of elements and their elements hold the same
string value, operator == returns false because it compares the addresses of the strings
rather than the strings themselves. You can alter this behavior by defining a specialized
version of operator == for type const char * exclusively, which compares the strings
rather than their addresses. The compiler picks the specialized version only when objects
of type Vector are compared. Otherwise, it uses the primary version of [ Pobierz całość w formacie PDF ]

  • zanotowane.pl
  • doc.pisz.pl
  • pdf.pisz.pl
  • szkla.opx.pl
  •