The full functionality of the C++ standard library requires not only thesupport of templates in general, but also many new standardized template features, including those discussed in th
Trang 1The core language and the library of C++ were standardized in parallel
In this way, the library could benefit from improvements in the languageand the language could benefit from experiences of library
implementation In fact, during the standardization process the libraryoften used special language features that were not yet available
C++ is not the same language it was five years ago If you didn't follow itsevolution, you may be surprised with the new language features used bythe library This section gives you a brief overview of those new features.For details, refer to books on the language in question
While I was writing this book (in 1998), not all compilers were able toprovide all of the new language features I hope (and expect) that this willchange very soon (most compiler vendors were part of the
standardization process) Thus, you may be restricted in your use of thelibrary Portable implementations of the library typically consider whetherfeatures are present in the environment they use (they usually have
some test programs to check which language features are present, andthen set preprocessor directives according to the result of the check) I'llmention any restrictions that are typical and important throughout thebook by using footnotes
The following subsections describe the most important new languagefeatures that are relevant for the C++ standard library
2.2.1 Templates
Almost all parts of the library are written as templates Without templatesupport, you can't use the standard library Moreover, the library needednew special template features, which I introduce after a short overview oftemplates
Templates are functions or classes that are written for one or more typesnot yet specified When you use a template, you pass the types as
arguments, explicitly or implicitly The following is a typical example afunction that returns the maximum of two values:
Trang 2Following the same principle, you can "parameterize" classes on arbitrarytypes This is useful for container classes You can implement the
container operations for an arbitrary element type The C++ standardlibrary provides many template container classes (for example, see
Chapter 6 or Chapter 10) It also uses template classes for many otherreasons For example, the string classes are parameterized on the type
of the characters and the properties of the character set (see Chapter
11)
A template is not compiled once to generate code usable for any type;instead, it is compiled for each type or combination of types for which it isused This leads to an important problem in the handling of templates inpractice: You must have the implementation of a template function
available when you call it, so that you can compile the function for yourspecific type Therefore, the only portable way of using templates at themoment is to implement them in header files by using inline functions.[4] [4] To avoid the problem of templates having to be present in header
files, the standard introduced a template compilation model with the
Trang 3The full functionality of the C++ standard library requires not only thesupport of templates in general, but also many new standardized
template features, including those discussed in the following paragraphs
Nontype Template Parameters
In addition to type parameters, it is also possible to use nontype
parameters A nontype parameter is then considered as part of the type.For example, for the standard class bitset<> (class bitset<> is
introduced in Section 10.4,) you can pass the number of bits as thetemplate argument The following statements define two bitfields, onewith 32 bits and one with 50 bits:
bitset<32> fIags32; // bitset with 32 bits bitset<50> flags50; // bitset with 50 bits
These bitsets have different types because they use different templatearguments Thus, you can't assign or compare them (except if a
If you pass only one argument, the default parameter is used as secondargument:
Trang 4Thus, ptr is a pointer to the type T::SubType Without typename,
SubType would be considered a static member Thus
T::SubType * ptr
would be a multiplication of value SubType of type T with ptr
According to the qualification of SubType being a type, any type that is
used in place of T must provide an inner type SubType For example,
Trang 5Apart from this, typename can also be used instead of class in a
Trang 10}
}
The throw statement starts a process called stack unwinding; that is,
any block or function is left as if there was a return statement
However, the program does not jump anywhere For all local objects thatare declared in the blocks that the program leaves due to the exceptiontheir destructors are called Stack unwinding continues until main() isleft, which ends the program, or until a catch clause "catches" andhandles the exception:
direction (from the bottom where the problem was found to the topwhere the problem is solved or handled) You can't process the
exception and continue from where you found the exception In thisregard, exception handling is completely different from signal
handling
Trang 12all identifiers in a namespace, the name of the namespace is the onlyglobal identifier that might conflict with other global symbols Similar tothe handling of classes, you have to qualify a symbol in a namespace bypreceding the identifier with the name of the namespace, separated bythe operator :: as follows:
defines logical modules instead of physical modules (in UML and other
modeling notations, a module is also called a package).
You don't have to qualify the namespace for functions if one or moreargument types are defined in the namespace of the function This rule is
Trang 13compiler will report an ambiguity if there also exists an identifier File or
Trang 142.2.5 Type bool
To provide better support for Boolean values, type bool was introduced
Using bool increases readability and allows you to overload behavior for
Boolean values The literals true and false were introduced as
Here, the use of explicit is rather important Without explicit this
constructor would define an automatic type conversion from int to
Stack If this happens, you could assign an int to a Stack:
Trang 15an implicit conversion
2.2.7 New Operators for Type Conversion
To enable you to clarify the meaning of an explicit type conversion for oneargument, the following four new operators were introduced:
1 static_cast
This operator converts a value logically It can be considered a
creation of a temporary object that is initialized by the value that getsconverted The conversion is allowed only if a type conversion isdefined (either as a built-in conversion rule or via a defined
conversion operation) For example:
float x;
Trang 16
reference and the type conversion fails, dynamic_cast throws a
bad_cast exception (bad_cast is described on page 26) Note
Trang 17that from a design point of view, it it always better to avoid such type-dependent statements when you program with polymorphic types
3 const_cast
This operator adds or removes the constness of a type In addition,
you can remove a volatile qualification Any other change of the
Trang 18It is now possible to initialize integral constant static members inside theclass structure This is useful when the constant is used in the class
Trang 19defined as char** Note that the return type int is required becausethe implicit int is deprecated
You may, but are not required to, end main() with a return statement.Unlike C, C++ defines an implicit
return 0;
at the end of main() This means that every program that leaves
main() without a return statement is successful (any value other than
0 represents a kind of failure) Because of this, my examples in this bookhave no return statement at the end of main() Note that some
compilers might print a warning message regarding this or even handle it
as error Well, that's life before the standard
Trang 20This chapter discusses STL containers in detail It continues the
discussion that was begun in Chapter 5 The chapter starts with a
general overview of the general abilities and operations of all containerclasses, with each container class explained in detail The explanationincludes a description of their internal data structures, their operations,and their performance It also shows how to use the different operationsand gives examples if the usage is not trivial Each section about thecontainers ends with examples of the typical use of the container Thechapter then discusses the interesting question of when to use whichcontainer By comparing the general abilities, advantages, and
disadvantages of all container types, it shows you how to find the bestcontainer to meet your needs Lastly, the chapter covers all members ofall container classes in detail This part is intended as a type of referencemanual You can find the minor details of the container interface and theexact signature of the container operations When useful,
crossreferences to similar or supplementary algorithms are included
The C++ standard library provides some special container classes, the
so-called container adapters (stack, queue, priority queue), bitmaps, and valarrays All of these have special interfaces that don't meet the general
Trang 21The C++ standard library provides not only the containers for the STLframework, but also some containers that fit some special needs andprovide simple, almost self-explanatory interfaces You can group thesecontainers into
The so-called container adapters
These containers adapt standard STL containers to fit special needs.There are three standard container adapters:
6.2.6
Trang 22This chapter presents the string types of the C++ standard library Itdescribes the basic template class basic_string<> and its standardspecializations string and wstring
the C++ standard library (whether it is string or wstring) For
"ordinary strings" of type char* or const char*, string.
I use the term C-Note that the type of string literals (such as "hello") was changed into
const char* However, to provide backward compatibility there is animplicit but deprecated conversion to char* for them
Trang 23Bitsets model fixed-sized arrays of bits or Boolean values They are
useful to manage sets of flags, where variables may represent any
combination of flags C and old C++ programs usually use type long forarrays of bits and manipulate the bits with the bit operators, such as &, |,and ~ The class bitset has the advantage that bitsets may contain anynumber of bits, and additional operations are provided For example, youcan assign single bits, and read and write bitsets as a sequence of zerosand ones
Note that you can't change the number of bits in a bitset The number ofbits is the template parameter If you need a container for a variable
Templates with different template arguments are different types You can
Trang 26cout << "267 as binary long: "
<< bitset<numeric_limits<unsigned long>::digits>(267) << endl;
short (see Section 4.3, for a discussion of numeric limits) The output
operator for bitset prints the bits as a sequence of characters 0 and 1
Similarly,
Trang 2710.4.2 Class bitset in Detail
The bitset class provides the following operations
Trang 28bitset<bits>::bitset (const string& str, string::size_type str_idx)
bitset<bits>::bitset (const string& str, string::size_type str_idx,
string::size_type str_num)
Trang 29Throw invalid_argument if one of the characters is neither '0'
Nonmanipulating Operations
Trang 30Throws out_of_range if idx > size()
bool bitset<bits>::operator == (const bitset<bits>& bits) const
Returns whether all bits of *this and bits have the same value.
bool bitset<bits>::operator != (const bitset<bits>& bits) const
Returns whether any bits of *this and bits have a different value.
Trang 31Returns the modified bitset
Throws out_of_range if idx > size()
bitset<bits>& bitset<bits>::set (size_t idx, int value)
Sets the bit at position idx according to value.
Returns the modified bitset
value is processed as a Boolean value If value is equal to 0, the bit
is set to false Any other value sets the bit to true
Throws out_of _range if idx > size()
Trang 32Throws out_of_range if idx > size()
bitset<bits>& bitset<bits>::operator \'88= (const bitset<bits>& bits)
Trang 33Returns the modified bitset
The last num bits are set to false
Access with Operator [ ]
bitset<bits>::reference bitset<bits>::operator [ ] (size_t idx)
bool bitset<bits>::operator [ ] (size_t idx) const
Both forms return the bit at position idx
The first form for nonconstant bitsets uses a proxy type to enable theuse of the return value as a modifiable value (lvalue) See the nextparagraphs for details
The caller must ensure that idx is a valid index; otherwise, the
behavior is undefined
Operator [ ] returns a special temporary object of type
bitset<>::reference when it is called for nonconstant bitsets Thatobject is used as a proxy[9] that allows certain modifications with the bitthat is accessed by operator [] In particular, for references the
Trang 35bitset<bits> operator | (const bitset<bits>& bits1, const
Trang 37See page 462 for an example.
Trang 38The class pair is provided to treat two values as a single unit It is used
in several places within the C++ standard library In particular, the
container classes map and multimap use pairs to manage their
elements, which are key/value pairs (See Section 6.6) Another
example of the usage of pairs is functions that return two values
The structure pair is defined in <utility> as follows:
Trang 42Numeric types in general have platform-dependent limits The C++
standard library provides these limits in the template numeric_limits
These numeric limits replace and supplement the ordinary preprocessorconstants of C These constants are still available for integer types in
<climits> and <limits.h>, and for floating-point types in <cfloat>
and <float.h> The new concept of numeric limits has two
advantages: First, it offers more type safety Second, it enables a
programmer to write templates that evaluate these limits
The numeric limits are discussed in the rest of this section Note,
however, that it is always better to write platform-independent code byusing the minimum guaranteed precision of the types These minimumvalues are provided in Table 4.1
is implemented for each type, where it is useful You can do this by
providing specialization of a general template numeric_limits is atypical example of this technique, which works as follows:
A general template provides the default numeric values for any type:
Trang 44Table 4.2 Members of Class numeric_limits<>, Part 1
Trang 45min() Minimum finite value
(minimum normalized value for floating-point types with denormalization; meaningful
if is bounded ||
!is_signed)
INT_MIN,FLT_MIN,CHAR_MIN,
Floating point: base of the
exponent representation FLT_RADIXmin_exponent Minimum negative integer