C/C++ Languages and C++ Libraries

Languages and Libraries for Visual C++

This information title contains reference material on the following subjects:
C++ Language
C Language
iostream Library
Standard C++ Library, including the Standard Template Library

Interesting home pages
Visual C++ Home The entire Visual C++ product.


C++ Language Reference

This manual explains the C++ programming language as it is implemented in Microsoft® C++. Microsoft C++ is based on The Annotated C++ Reference Manual by Margaret Ellis and Bjarne Stroustrup (the ANSI base document for C++) and the current working paper for the draft proposed standard. For information about the Microsoft C compiler, see the C Language Reference.

Organization of the C++ Language Reference
Interesting home pages
Visual C++ Home Visual C++ at a glance.
Run-Time Library Reference Alphabetic reference to the standard C library of functions.
Class Library Reference Alphabetic reference to the Microsoft Foundation classes.
iostream Class Library Reference Alphabetic reference to the class library for I/O operations.


Organization of the C++ Language Reference

Chapter 1, Lexical Conventions, introduces the fundamental elements of a C++ program as they are meaningful to the compiler. These elements, called “lexical elements,” are used to construct statements, definitions, declarations, and so on, which are used to construct complete programs.

Chapter 2, Basic Concepts, explains concepts such as scope, linkage, program startup and termination, storage classes, and types. These concepts are key to understanding C++. Terminology used in this book is also introduced.

Chapter 3, Standard Conversions, describes the type conversions the compiler performs between built-in, or “fundamental,” types. It also explains how the compiler performs conversions among pointer, reference, and pointer-to-member types.

Chapter 4, Expressions, describes C++ expressions — sequences of operators and operands that are used for computing values, designating objects or functions, or generating other side effects.

Chapter 5, Statements, explains the C++ program elements that control how and in what order programs are executed. Among the statements covered are expression statements, null statements, compound statements, selection statements, iteration statements, jump statements, and declaration statements.

Chapter 6, Declarations, is one of three chapters devoted to how complete declarations are used to form declaration statements. This chapter describes such topics as storage-class specifiers, function definitions, initializations, enumerations, class, struct, and union declarations, and typedef declarations. Related information can be found in Chapter 7, Declarators, and Appendix B, Microsoft-Specific Modifiers.

Chapter 7, Declarators, explains the portion of a declaration statement that names an object, type, or function.

Chapter 8, Classes, introduces C++ classes. C++ treats an object declared with the class, struct, or union keyword as a class type. This chapter explains how to use these class types.

Chapter 9, Derived Classes, covers the details of inheritance — a process by which you can define a new type as having all the attributes of an existing type, plus any new attributes you add.

Chapter 10, Member-Access Control, explains how you can control access to class members. Use of access-control specifiers can help produce more robust code because you can limit the number of ways an object’s state can be changed.

Chapter 11, Special Member Functions, describes special functions unique to class types. These special functions perform initialization (constructor functions), cleanup (destructor functions), and conversions. This chapter also describes the new and delete operators, which are used for dynamic memory allocation.

Chapter 12, Overloading, explains a C++ feature that enables you to define a group of functions with the same name but different arguments. Which function in the group is called depends on the argument list in the actual function call. In addition, this chapter covers overloaded operators, a mechanism for defining your own behavior for C++ operators.

Appendix A, Grammar Summary, is a summary of the C++ grammar with the Microsoft extensions. Portions of this grammar are shown throughout this manual in “Syntax” sections.

Appendix B, Microsoft-Specific Modifiers, describes the modifiers specific to Microsoft C++. These modifiers control memory addressing, calling conventions, and so on.

Appendix C, Compiler COM Support Classes, is a reference to four Microsoft-specific classes used to support some Component Object Model types.

Appendix D, Charts, contains the following charts: ASCII Character Codes, ASCII Multilingual Codes, ANSI Character Codes, and Key Codes.


Scope of this Manual

C++, like C, is a language that is heavily reliant on a rich set of library functions to provide the following:

  • Portable operating-system interface (file and screen I/O)

  • String and buffer manipulation

  • Floating-point math transformations

  • Other supporting functionality

For information about the run-time library functions, see the Run-Time Library Reference. For information on the Microsoft Foundation classes or the iostream classes, see the Class Library Reference or the iostream Class Library Reference, respectively.


Special Terminology in this Manual

In this manual, the term “argument” refers to the entity that is passed to a function. In some cases, it is modified by “actual” or “formal,” which mean the argument expression specified in the function call and the argument declaration specified in the function definition, respectively.

The term “variable” refers to a simple C-type data object. The term “object” refers to both C++ objects and variables; it is an inclusive term.

For more information on terminology, see Terms.


Lexical Conventions

This chapter introduces the fundamental elements of a C++ program. You use these elements, called “lexical elements” or “tokens” to construct statements, definitions, declarations, and so on, which are used to construct complete programs. The following lexical elements are discussed in this chapter:

  • Tokens

  • Comments

  • Identifiers

  • C++ keywords

  • Punctuators

  • Operators

  • Literals

This chapter also includes Table 1.1, which shows the precedence and associativity of C++ operators (from highest to lowest precedence). For a complete discussion of operators, see Chapter 4, Expressions.


Overview of File Translation

C++ programs, like C programs, consist of one or more files. Each of these files is translated in the following conceptual order (the actual order follows the “as if” rule: translation must occur as if these steps had been followed):

  1. Lexical tokenizing. Character mapping and trigraph processing, line splicing, and tokenizing are performed in this translation phase.

  2. Preprocessing. This translation phase brings in ancillary source files referenced by #include directives, handles “stringizing” and “charizing” directives, and performs token pasting and macro expansion (see Preprocessor Directives in the Preprocessor Reference for more information). The result of the preprocessing phase is a sequence of tokens that, taken together, define a “translation unit.”

    Preprocessor directives always begin with the number-sign (#) character (that is, the first nonwhite-space character on the line must be a number sign). Only one preprocessor directive can appear on a given line. For example:

    #include <iostream.h>  // Include text of iostream.h in
                       //  translation unit.
#define NDEBUG         // Define NDEBUG (NDEBUG contains empty
                       //  text string).
  3. Code generation. This translation phase uses the tokens generated in the preprocessing phase to generate object code.

    During this phase, syntactic and semantic checking of the source code is performed.

See Phases of Translation in the Preprocessor Reference for more information.

The C++ preprocessor is a strict superset of the ANSI C preprocessor, but the C++ preprocessor differs in a few instances. The following list describes several differences between the ANSI C and the C++ preprocessors:

  • Single-line comments are supported. See Comments for more information.

  • One predefined macro, __cplusplus, is defined only for C++. See Predefined Macros in the Preprocessor Reference for more information.

  • The C preprocessor does not recognize the C++ operators: .*, –>*, and ::. See Operators and Chapter 4, Expressions. for more information about operators.


C++ Tokens

A token is the smallest element of a C++ program that is meaningful to the compiler. The C++ parser recognizes these kinds of tokens: identifiers, keywords, literals, operators, punctuators, and other separators. A stream of these tokens makes up a translation unit.

Tokens are usually separated by “white space.” White space can be one or more:

  • Blanks

  • Horizontal or vertical tabs

  • New lines

  • Formfeeds

  • Comments

Syntax

token :

keyword
identifier
constant
operator
punctuator

preprocessing-token :

header-name
identifier
pp-number
character-constant
string-literal
operator
punctuator
each nonwhite-space character that cannot be one of the above

The parser separates tokens from the input stream by creating the longest token possible using the input characters in a left-to-right scan. Consider this code fragment:

a = i+++j;

The programmer who wrote the code might have intended either of these two statements:

a = i + (++j)

a = (i++) + j

Because the parser creates the longest token possible from the input stream, it chooses the second interpretation, making the tokens i++, +, and j.


C++ Comments

A comment is text that the compiler ignores but that is useful for programmers. Comments are normally used to annotate code for future reference. The compiler treats them as white space. You can use comments in testing to make certain lines of code inactive; however, #if/#endif preprocessor directives work better for this because you can surround code that contains comments but you cannot nest comments.

A C++ comment is written in one of the following ways:

  • The /* (slash, asterisk) characters, followed by any sequence of characters (including new lines), followed by the */ characters. This syntax is the same as ANSI C.

  • The // (two slashes) characters, followed by any sequence of characters. A new line not immediately preceded by a backslash terminates this form of comment. Therefore, it is commonly called a “single-line comment.”

The comment characters (/*, */, and //) have no special meaning within a character constant, string literal, or comment. Comments using the first syntax, therefore, cannot be nested. Consider this example:

/* Intent:  Comment out this block of code.
   Problem: Nested comments on each line of code are illegal.
FileName = String( "hello.dat" ); /* Initialize file string */
cout << "File: " << FileName << "\n"; /* Print status message */
*/

The preceding code will not compile because the compiler scans the input stream from the first /* to the first */ and considers it a comment. In this case, the first */ occurs at the end of the Initialize file string comment. The last */, then, is no longer paired with an opening /*.

Note that the single-line form (//) of a comment followed by the line-continuation token (\) can have surprising effects. Consider this code:

#include <stdio.h>

void main()
{
    printf( "This is a number %d", // \
             5 );
}

After preprocessing, the preceding code contains errors and appears as follows:

#include <stdio.h>

void main()
{
    printf( "This is a number %d",
}


C++ Identifiers

An identifier is a sequence of characters used to denote one of the following:

  • Object or variable name

  • Class, structure, or union name

  • Enumerated type name

  • Member of a class, structure, union, or enumeration

  • Function or class-member function

  • typedef name

  • Label name

  • Macro name

  • Macro parameter

Syntax

identifier :

nondigit
identifier nondigit
identifier digit

nondigit : one of

_ a b c d e f g h i j k l m
n o p q r s t u v w x y z
A B C D E F G H I J K L M
N O P Q R S T U V W X Y Z

digit : one of

0 1 2 3 4 5 6 7 8 9

Microsoft Specific

Only the first 247 characters of Microsoft C++ identifiers are significant. This restriction is complicated by the fact that names for user-defined types are “decorated” by the compiler to preserve type information. The resultant name, including the type information, cannot be longer than 247 characters. (See Decorated Names in the Visual C++ Programmer’s Guide for more information.) Factors that can influence the length of a decorated identifier are:

  • Whether the identifier denotes an object of user-defined type or a type derived from a user-defined type.

  • Whether the identifier denotes a function or a type derived from a function.

  • The number of arguments to a function.

END Microsoft Specific

The first character of an identifier must be an alphabetic character, either uppercase or lowercase, or an underscore ( _ ). Because C++ identifiers are case sensitive, fileName is different from FileName.

Identifiers cannot be exactly the same spelling and case as keywords. Identifiers that contain keywords are legal. For example, Pint is a legal identifier, even though it contains int, which is a keyword.

Use of two sequential underscore characters ( __ ) at the beginning of an identifier, or a single leading underscore followed by a capital letter, is reserved for C++ implementations in all scopes. You should avoid using one leading underscore followed by a lowercase letter for names with file scope because of possible conflicts with current or future reserved identifiers.


C++ Keywords

Keywords are predefined reserved identifiers that have special meanings. They cannot be used as identifiers in your program. The following keywords are reserved for C++:

Syntax

keyword: one of

asm1 | auto | bad_cast | bad_typeid
bool | break | case | catch
char | class | const | const_cast
continue | default | delete | do
double | dynamic_cast | else | enum
except | explicit | extern | false
finally | float | for | friend
goto | if | inline | int
long | mutable | namespace | new
operator | private | protected | public
register | reinterpret_cast | return | short
signed | sizeof | static | static_cast
struct | switch | template | this
throw | true | try | type_info
typedef | typeid | typename | union
unsigned | using | virtual | void
volatile | while |  |

1 Reserved for compatibility with other C++ implementations, but not implemented. Use __asm.

Microsoft Specific

In Microsoft C++, identifiers with two leading underscores are reserved for compiler implementations. Therefore, the Microsoft convention is to precede Microsoft-specific keywords with double underscores. These words cannot be used as identifier names.

allocate3 | __inline | property3
__asm1 | __int8 | selectany3
__based2 | __int16 | __single_inheritance
__cdecl | __int32 | __stdcall
__declspec | __int64 | thread3
dllexport3 | __leave | __try
dllimport3 | __multiple_inheritance | uuid3
__except | naked3 | __uuidof
__fastcall | nothrow3 | __virtual_inheritance
__finally |  |

1 Replaces C++ asm syntax.

2 The __based keyword has limited uses for 32-bit target compilations.

3 These are special identifiers when used with __declspec; their use in other contexts is not restricted.

Microsoft extensions are enabled by default. To ensure that your programs are fully portable, you can disable Microsoft extensions by specifying the ANSI-compatible /Za command-line option (compile for ANSI compatibility) during compilation. When you do this, Microsoft-specific keywords are disabled.

When Microsoft extensions are enabled, you can use the previously-listed keywords in your programs. For ANSI compliance, these keywords are prefaced by a double underscore. For backward compatibility, single-underscore versions of all the keywords except __except, __finally, __leave, and __try are supported. In addition, __cdecl is available with no leading underscore.

END Microsoft Specific


C++ Punctuators

Punctuators in C++ have syntactic and semantic meaning to the compiler but do not, of themselves, specify an operation that yields a value. Some punctuators, either alone or in combination, can also be C++ operators or be significant to the preprocessor.

Syntax

punctuator : one of

! % ^ & * ( ) – + = { } | ~
[ ] \ ; ' : " < > ? , . / #

The punctuators [ ], ( ), and { } must appear in pairs after translation phase 4.


C++ Operators

Operators specify an evaluation to be performed on one of the following:

  • One operand (unary operator)

  • Two operands (binary operator)

  • Three operands (ternary operator)

The C++ language includes all C operators and adds several new operators. Table 1.1 lists the operators available in Microsoft C++.

Operators follow a strict precedence which defines the evaluation order of expressions containing these operators. Operators associate with either the expression on their left or the expression on their right; this is called “associativity.” Operators in the same group have equal precedence and are evaluated left to right in an expression unless explicitly forced by a pair of parentheses, ( ). Table 1.1 shows the precedence and associativity of C++ operators (from highest to lowest precedence).

Table 1.1 C++ Operator Precedence and Associativity

Operator | Name or Meaning | Associativity
:: | Scope resolution | None
:: | Global | None
[ ] | Array subscript | Left to right
( ) | Function call | Left to right
( ) | Conversion | None
. | Member selection (object) | Left to right
–> | Member selection (pointer) | Left to right
++ | Postfix increment | None
–– | Postfix decrement | None
new | Allocate object | None
delete | Deallocate object | None
delete[ ] | Deallocate object | None
++ | Prefix increment | None
–– | Prefix decrement | None
* | Dereference | None
& | Address-of | None
+ | Unary plus | None
– | Arithmetic negation (unary) | None
! | Logical NOT | None
~ | Bitwise complement | None
sizeof | Size of object | None
sizeof ( ) | Size of type | None
typeid( ) | type name | None
(type) | Type cast (conversion) | Right to left
const_cast | Type cast (conversion) | None
dynamic_cast | Type cast (conversion) | None
reinterpret_cast | Type cast (conversion) | None
static_cast | Type cast (conversion) | None
.* | Apply pointer to class member (objects) | Left to right
–>* | Dereference pointer to class member | Left to right
* | Multiplication | Left to right
/ | Division | Left to right
% | Remainder (modulus) | Left to right
+ | Addition | Left to right
– | Subtraction | Left to right
<< | Left shift | Left to right
>> | Right shift | Left to right
< | Less than | Left to right
> | Greater than | Left to right
<= | Less than or equal to | Left to right
>= | Greater than or equal to | Left to right
== | Equality | Left to right
!= | Inequality | Left to right
& | Bitwise AND | Left to right
^ | Bitwise exclusive OR | Left to right
| | Bitwise OR | Left to right
&& | Logical AND | Left to right
|| | Logical OR | Left to right
e1?e2:e3 | Conditional | Right to left
= | Assignment | Right to left
*= | Multiplication assignment | Right to left
/= | Division assignment | Right to left
%= | Modulus assignment | Right to left
+= | Addition assignment | Right to left
–= | Subtraction assignment | Right to left
<<= | Left-shift assignment | Right to left
>>= | Right-shift assignment | Right to left
&= | Bitwise AND assignment | Right to left
|= | Bitwise inclusive OR assignment | Right to left
^= | Bitwise exclusive OR assignment | Right to left
, | Comma | Left to right


Literals

Invariant program elements are called “literals” or “constants.” The terms “literal” and “constant” are used interchangeably here. Literals fall into four major categories: integer, character, floating-point, and string literals.

Syntax

literal :

integer-constant
character-constant
floating-constant
string-literal


C++ Integer Constants

Integer constants are constant data elements that have no fractional parts or exponents. They always begin with a digit. You can specify integer constants in decimal, octal, or hexadecimal form. They can specify signed or unsigned types and long or short types.

Syntax

integer-constant :

decimal-constant integer-suffixopt
octal-constant integer-suffixopt
hexadecimal-constant integer-suffixopt
'c-char-sequence'

decimal-constant :

nonzero-digit
decimal-constant digit

octal-constant :

0
octal-constant octal-digit

hexadecimal-constant :

0x hexadecimal-digit
0X hexadecimal-digit
hexadecimal-constant hexadecimal-digit

nonzero-digit : one of

1 2 3 4 5 6 7 8 9

octal-digit : one of

0 1 2 3 4 5 6 7

hexadecimal-digit : one of

0 1 2 3 4 5 6 7 8 9
a b c d e f
A B C D E F

integer-suffix :

unsigned-suffix long-suffixopt
long-suffix unsigned-suffixopt

unsigned-suffix : one of

u U

long-suffix : one of

l L

64-bit integer-suffix :

i64

To specify integer constants using octal or hexadecimal notation, use a prefix that denotes the base. To specify an integer constant of a given integral type, use a suffix that denotes the type.

To specify a decimal constant, begin the specification with a nonzero digit. For example:

int i = 157;   // Decimal constant
int j = 0198;  // Not a decimal number; erroneous octal constant
int k = 0365;  // Leading zero specifies octal constant, not decimal

To specify an octal constant, begin the specification with 0, followed by a sequence of digits in the range 0 through 7. The digits 8 and 9 are errors in specifying an octal constant. For example:

int i = 0377;   // Octal constant
int j = 0397;   // Error: 9 is not an octal digit

To specify a hexadecimal constant, begin the specification with 0x or 0X (the case of the “x” does not matter), followed by a sequence of digits in the range 0 through 9 and a (or A) through f (or F). Hexadecimal digits a (or A) through f (or F) represent values in the range 10 through 15. For example:

int i = 0x3fff;   // Hexadecimal constant
int j = 0X3FFF;   // Equal to i

To specify an unsigned type, use either the u or U suffix. To specify a long type, use either the l or L suffix. For example:

unsigned uVal = 328u;             // Unsigned value
long lVal = 0x7FFFFFL;            // Long value specified
                                  //  as hex constant
unsigned long ulVal = 0776745ul;  // Unsigned long value


C++ Character Constants

Character constants are one or more members of the “source character set,” the character set in which a program is written, surrounded by single quotation marks ('). They are used to represent characters in the “execution character set,” the character set on the machine where the program executes.

Microsoft Specific

For Microsoft C++, the source and execution character sets are both ASCII.

END Microsoft Specific

There are three kinds of character constants:

  • Normal character constants

  • Multicharacter constants

  • Wide-character constants

Note Use wide-character constants in place of multicharacter constants to ensure portability.

Character constants are specified as one or more characters enclosed in single quotation marks. For example:

char ch = 'x';          // Specify normal character constant.
int mbch = 'ab';        // Specify system-dependent
                        //  multicharacter constant.
wchar_t wcch = L'ab';   // Specify wide-character constant.

Note that mbch is of type int. If it were declared as type char, the second byte would not be retained. A multicharacter constant has four meaningful characters; specifying more than four generates an error message.

Syntax

character-constant :

'c-char-sequence'
L'c-char-sequence'

c-char-sequence :

c-char
c-char-sequence c-char

c-char :

any member of the source character set except the single quotation mark ('), backslash (\), or newline character
escape-sequence

escape-sequence :

simple-escape-sequence
octal-escape-sequence
hexadecimal-escape-sequence

simple-escape-sequence : one of

\' \" \? \\
\a \b \f \n \r \t \v

octal-escape-sequence :

\octal-digit
\octal-digit octal-digit
\octal-digit octal-digit octal-digit

hexadecimal-escape-sequence :

\x hexadecimal-digit
hexadecimal-escape-sequence hexadecimal-digit

Microsoft C++ supports normal, multicharacter, and wide-character constants. Use wide-character constants to specify members of the extended execution character set (for example, to support an international application). Normal character constants have type char, multicharacter constants have type int, and wide-character constants have type wchar_t. (The type wchar_t is defined in the standard include files STDDEF.H, STDLIB.H, and STRING.H. The wide-character functions, however, are prototyped only in STDLIB.H.)

The only difference in specification between normal and wide-character constants is that wide-character constants are preceded by the letter L. For example:

char schar = 'x';               // Normal character constant
wchar_t wchar = L'\x81\x19';    // Wide-character constant

Table 1.2 shows reserved or nongraphic characters that are system dependent or not allowed within character constants. These characters should be represented with escape sequences.

Table 1.2 C++ Reserved or Nongraphic Characters

Character | ASCII Representation | ASCII Value | Escape Sequence
Newline | NL (LF) | 10 or 0x0a | \n
Horizontal tab | HT | 9 | \t
Vertical tab | VT | 11 or 0x0b | \v
Backspace | BS | 8 | \b
Carriage return | CR | 13 or 0x0d | \r
Formfeed | FF | 12 or 0x0c | \f
Alert | BEL | 7 | \a
Backslash | \ | 92 or 0x5c | \\
Question mark | ? | 63 or 0x3f | \?
Single quotation mark | ' | 39 or 0x27 | \'
Double quotation mark | " | 34 or 0x22 | \"
Octal number | ooo | — | \ooo
Hexadecimal number | hhh | — | \xhhh
Null character | NUL | 0 | \0

If the character following the backslash does not specify a legal escape sequence, the result is implementation defined. In Microsoft C++, the character following the backslash is taken literally, as though the escape were not present, and a level 1 warning (“unrecognized character escape sequence”) is issued.

Octal escape sequences, specified in the form \ooo, consist of a backslash and one, two, or three octal characters. Hexadecimal escape sequences, specified in the form \xhhh, consist of the characters \x followed by a sequence of hexadecimal digits. Unlike octal escape constants, there is no limit on the number of hexadecimal digits in an escape sequence.

Octal escape sequences are terminated by the first character that is not an octal digit, or when three characters are seen. For example:

wchar_t och = L'\076a';  // Sequence terminates at a
char    ch = '\233';     // Sequence terminates after 3 characters

Similarly, hexadecimal escape sequences terminate at the first character that is not a hexadecimal digit. Because hexadecimal digits include the letters a through f (and A through F), make sure the escape sequence terminates at the intended digit.

Because the single quotation mark (') encloses character constants, use the escape sequence \' to represent enclosed single quotation marks. The double quotation mark (") can be represented without an escape sequence. The backslash character (\) is a line-continuation character when placed at the end of a line. If you want a backslash character to appear within a character constant, you must type two backslashes in a row (\\). (See Phases of Translation in the Preprocessor Reference for more information about line continuation.)


C++ Floating-Point Constants

Floating-point constants specify values that must have a fractional part. These values contain decimal points (.) and can contain exponents.

Syntax

floating-constant :

fractional-constant exponent-partopt floating-suffixopt
digit-sequence exponent-part floating-suffixopt

fractional-constant :

digit-sequenceopt . digit-sequence
digit-sequence .

exponent-part :

e signopt digit-sequence
E signopt digit-sequence

sign : one of

+ –

digit-sequence :

digit
digit-sequence digit

floating-suffix :one of

f l F L

Floating-point constants have a “mantissa,” which specifies the value of the number, an “exponent,” which specifies the magnitude of the number, and an optional suffix that specifies the constant’s type. The mantissa is specified as a sequence of digits followed by a period, followed by an optional sequence of digits representing the fractional part of the number. For example:

18.46
38.

The exponent, if present, specifies the magnitude of the number as a power of 10, as shown in the following example:

18.46e0      // 18.46
18.46e1      // 184.6

If an exponent is present, the trailing decimal point is unnecessary in whole numbers such as 18E0.

Floating-point constants default to type double. By using the suffixes f or l (or F or L — the suffix is not case sensitive), the constant can be specified as float or long double, respectively.

Although long double and double have the same representation, they are not the same type. For example, you can have overloaded functions like

void func( double );

and

void func( long double );


C++ String Literals

A string literal consists of zero or more characters from the source character set surrounded by double quotation marks ("). A string literal represents a sequence of characters that, taken together, form a null-terminated string.

Syntax

string-literal :

"s-char-sequenceopt"
L"s-char-sequenceopt"

s-char-sequence :

s-char
s-char-sequence s-char

s-char :

any member of the source character set except the double quotation mark ("), backslash (\), or newline character
escape-sequence

C++ strings have these types:

  • Array of char[n], where n is the length of the string (in characters) plus 1 for the terminating '\0' that marks the end of the string

  • Array of wchar_t, for wide-character strings

The result of modifying a string constant is undefined. For example:

char *szStr = "1234";
szStr[2] = 'A';      // Results undefined

Microsoft Specific

In some cases, identical string literals can be “pooled” to save space in the executable file. In string-literal pooling, the compiler causes all references to a particular string literal to point to the same location in memory, instead of having each reference point to a separate instance of the string literal. The /Gf compiler option enables string pooling.

END Microsoft Specific

When specifying string literals, adjacent strings are concatenated. Therefore, this declaration:

char szStr[] = "12" "34";

is identical to this declaration:

char szStr[] = "1234";

This concatenation of adjacent strings makes it easy to specify long strings across multiple lines:

cout << "Four score and seven years "
        "ago, our forefathers brought forth "
        "upon this continent a new nation.";

In the preceding example, the entire string Four score and seven years ago, our forefathers brought forth upon this continent a new nation. is spliced together. This string can also be specified using line splicing as follows:

cout << "Four score and seven years \
ago, our forefathers brought forth \
upon this continent a new nation.";

After all adjacent strings in the constant have been concatenated, the NULL character, '\0', is appended to provide an end-of-string marker for C string-handling functions.

When the first string contains an escape character, string concatenation can yield surprising results. Consider the following two declarations:

char szStr1[] = "\01" "23";
char szStr2[] = "\0123";

Although it is natural to assume that szStr1 and szStr2 contain the same values, the values they actually contain are shown in Figure 1.1.

Figure 1.1 Escapes and String Concatenation

Microsoft Specific

The maximum length of a string literal is approximately 2,048 bytes. This limit applies to strings of type char[] and wchar_t[]. If a string literal consists of parts enclosed in double quotation marks, the preprocessor concatenates the parts into a single string, and for each line concatenated, it adds an extra byte to the total number of bytes.

For example, suppose a string consists of 40 lines with 50 characters per line (2,000 characters), and one line with 7 characters, and each line is surrounded by double quotation marks. This adds up to 2,007 bytes plus one byte for the terminating null character, for a total of 2,008 bytes. On concatenation, an extra character is added to the total number of bytes for each of the first 40 lines. This makes a total of 2,048 bytes. (The extra characters are not actually written to the string.) Note, however, that if line continuations (\) are used instead of double quotation marks, the preprocessor does not add an extra character for each line.

END Microsoft Specific

Determine the size of string objects by counting the number of characters and adding 1 for the terminating '\0' or 2 for type wchar_t.

Because the double quotation mark (") encloses strings, use the escape sequence (\") to represent enclosed double quotation marks. The single quotation mark (') can be represented without an escape sequence. The backslash character (\) is a line-continuation character when placed at the end of a line. If you want a backslash character to appear within a string, you must type two backslashes (\\). (See Phases of Translation in the Preprocessor Reference for more information about line continuation.)

To specify a string of type wide-character (wchar_t[]), precede the opening double quotation mark with the character L. For example:

wchar_t wszStr[] = L"1a1g";

All normal escape codes listed in Character Constants are valid in string constants. For example:

cout << "First line\nSecond line";
cout << "Error! Take corrective action\a";

Because the escape code terminates at the first character that is not a hexadecimal digit, specification of string constants with embedded hexadecimal escape codes can cause unexpected results. The following example is intended to create a string literal containing ASCII 5, followed by the characters five:

\x05five"

The actual result is a hexadecimal 5F, which is the ASCII code for an underscore, followed by the characters ive. The following example produces the desired results:

"\005five"     // Use octal constant.
"\x05" "five"  // Use string splicing.


Basic Concepts

This chapter explains concepts that are critical to understanding C++. C programmers will be familiar with many of these concepts, but there are some subtle differences that can cause unexpected program results. The following topics are included:

  • Terms

  • Declarations and definitions

  • Scope of a C++ object or function

  • Program definition and linkage rules

  • Startup and termination

  • Storage classes

  • Types

Additional topics include l-values, r-values, and numerical limits.


Terms

C++ terms used in this book are defined in Table 2.1:

Table 2.1 C++ Terminology

Term | Meaning
Declaration | A declaration introduces names and their types into a program without necessarily defining an associated object or function. However, many declarations serve as definitions.
Definition | A definition provides information that allows the compiler to allocate memory for objects or generate code for functions.
Lifetime | The lifetime of an object is the period during which an object exists, including its creation and destruction.
Linkage | Names can have external linkage, internal linkage, or no linkage. Within a program (a set of translation units), only names with external linkage denote the same object or function. Within a translation unit, names with either internal or external linkage denote the same object or function (except when functions are overloaded). (For more information on translation units, see Phases of Translation), in the Preprocessor Reference.) Names with no linkage denote unique objects or functions.
Name | A name denotes an object, function, set of overloaded functions, enumerator, type, class member, template, value, or label. C++ programs use names to refer to their associated language element. Names can be type names or identifiers.
Object An object is an instance (a data item) of a user-defined type (a class type). The difference between an object and a variable is that variables retain state information, whereas objects can also have behavior.

This manual draws a distinction between objects and variables: “object” means instance of a user-defined type, whereas “variable” means instance of a fundamental type.

In cases where either object or variable is applicable, the term “object” is used as the inclusive term, meaning “object or variable.”
Scope | Names can be used only within specific regions of program text. These regions are called the scope of the name.
Storage class | The storage class of a named object determines its lifetime, initialization, and, in certain cases, its linkage.
Type | Names have associated types that determine the meaning of the value or values stored in an object or returned by a function.
Variable | A variable is a data item of a fundamental type (for example, int, float, or double). Variables store state information but define no behavior for how that information is handled. See the preceding list item “Object” for information about how the terms “variable” and “object” are used in this documentation.


C++ Declarations and Definitions

Declarations tell the compiler that a program element or name exists. Definitions specify what code or data the name describes. A name must be declared before it can be used.


C++ Declarations

A declaration introduces one or more names into a program. Declarations can occur more than once in a program. Therefore, classes, structures, enumerated types, and other user-defined types can be declared for each compilation unit. The constraint on this multiple declaration is that all declarations must be identical. Declarations also serve as definitions, except when the declaration:

  • Is a function prototype (a function declaration with no function body).

  • Contains the extern specifier but no initializer (objects and variables) or function body (functions). This signifies that the definition is not necessarily in the current translation unit and gives the name external linkage.

  • Is of a static data member inside a class declaration.

    Because static class data members are discrete variables shared by all objects of the class, they must be defined and initialized outside the class declaration. (For more information about classes and class members, see Chapter 8, Classes.)

  • Is a class name declaration with no following definition, such as class T;.

  • Is a typedef statement.

Examples of declarations that are also definitions are:

// Declare and define int variables i and j.
int i;
int j = 10;

// Declare enumeration suits.
enum suits { Spades = 1, Clubs, Hearts, Diamonds };

// Declare class CheckBox.
class CheckBox : public Control
{
public:
            Boolean IsChecked();
    virtual int     ChangeState() = 0;
};

Some declarations that are not definitions are:

extern int i;
char *strchr( const char *Str, const char Target );


C++ Definitions

A definition is a unique specification of an object or variable, function, class, or enumerator. Because definitions must be unique, a program can contain only one definition for a given program element.

There can be a many-to-one correspondence between declarations and definitions. There are two cases in which a program element can be declared and not defined:

  • A function is declared but never referenced with a function call or with an expression that takes the function’s address.

  • A class is used only in a way that does not require its definition be known. However, the class must be declared. The following code illustrates such a case:
    class WindowCounter;    // Forward reference; no definition

class Window
{
    static WindowCounter windowCounter;  // Definition of
                                         //  WindowCounter
                                         //  not required.
};


Scope

C++ names can be used only in certain regions of a program. This area is called the “scope” of the name. Scope determines the “lifetime” of a name that does not denote an object of static extent. Scope also determines the visibility of a name, when class constructors and destructors are called, and when variables local to the scope are initialized. (For more information, see Constructors and Destructors in Chapter 11.) There are five kinds of scope:

  • Local scope. A name declared within a block is accessible only within that block and blocks enclosed by it, and only after the point of declaration. The names of formal arguments to a function in the scope of the outermost block of the function have local scope, as if they had been declared inside the block enclosing the function body. Consider the following code fragment:
    {
    int i;
}

    Because the declaration of i is in a block enclosed by curly braces, i has local scope and is never accessible because no code accesses it before the closing curly brace.

  • Function scope. Labels are the only names that have function scope. They can be used anywhere within a function but are not accessible outside that function.

  • File scope. Any name declared outside all blocks or classes has file scope. It is accessible anywhere in the translation unit after its declaration. Names with file scope that do not declare static objects are often called “global” names.

  • Class scope. Names of class members have class scope. Class member functions can be accessed only by using the member-selection operators (. or –>) or pointer-to-member operators (.* or –>*) on an object or pointer to an object of that class; nonstatic class member data is considered local to the object of that class. Consider the following class declaration:
    class Point
{
    int x;
    int y;
};

    The class members x and y are considered to be in the scope of class Point.

  • Prototype scope. Names declared in a function prototype are visible only until the end of the prototype. The following prototype declares two names (szDest, szSource); these names go out of scope at the end of the prototype:
    char *strcpy( char *szDest, const char *szSource );


Point of Declaration

A name is considered to be declared immediately after its declarator but before its (optional) initializer. (For more information on declarators, see Chapter 7, Declarators.) An enumerator is considered to be declared immediately after the identifier that names it but before its (optional) initializer.

Consider this example:

double dVar = 7.0;

void main()
{
    double dVar = dVar;
}

If the point of declaration were after the initialization, then the local dVar would be initialized to 7.0, the value of the global variable dVar. However, since that is not the case, dVar is initialized to an undefined value.

Enumerators follow the same rule. However, enumerators are exported to the enclosing scope of the enumeration. In the following example, the enumerators Spades, Clubs, Hearts, and Diamonds are declared. Because the enumerators are exported to the enclosing scope, they are considered to have global scope. The identifiers in the example are already defined in global scope.

Consider the following code:

const int Spades = 1, Clubs = 2, Hearts = 3, Diamonds = 4;

enum Suits
{
    Spades = Spades,     // error
    Clubs,               // error
    Hearts,              // error
    Diamonds             // error
};

Because the identifiers in the preceding code are already defined in global scope, an error message is generated.

Note Using the same name to refer to more than one program element — for example, an enumerator and an object — is considered poor programming practice and should be avoided. In the preceding example, this practice causes an error.


Hiding Names

You can hide a name by declaring it in an enclosed block. In Figure 2.1, i is redeclared within the inner block, thereby hiding the variable associated with i in the outer block scope.

Figure 2.1 Block Scope and Name Hiding

The output from the program shown in Figure 2.1 is:

i = 0
i = 7
j = 9
i = 0

Note The argument szWhat is considered to be in the scope of the function. Therefore, it is treated as if it had been declared in the outermost block of the function.


Hiding Names with File Scope

You can hide names with file scope by explicitly declaring the same name in block scope. However, file-scope names can be accessed using the scope-resolution operator (::). For example:

#include <iostream.h>

int i = 7;      // i has file scope--declared
                // outside all blocks

void main( int argc, char *argv[] )
{
   int i = 5;  // i has block scope--hides
                // the i with file scope

   cout << "Block-scoped i has the value: " << i << "\n";
   cout << "File-scoped i has the value: " << ::i << "\n";
}

The result of the preceding code is:

Block-scoped i has the value: 5
File-scoped i has the value: 7


Hiding Class Names

You can hide class names by declaring a function, object or variable, or enumerator in the same scope. However, the class name can still be accessed when prefixed by the keyword class.

// Declare class Account at file scope.
class Account
{
public:
    Account( double InitialBalance )
        { balance = InitialBalance; }
    double GetBalance()
        { return balance; }
private:
    double balance;
};

double Account = 15.37;            // Hides class name Account

void main()
{
    class Account Checking( Account ); // Qualifies Account as
                                       //  class name

    cout << "Opening account with balance of: "
         << Checking.GetBalance() << "\n";
}

Note that any place the class name (Account) is called for, the keyword class must be used to differentiate it from the file-scoped variable Account. This rule does not apply when the class name occurs on the left side of the scope-resolution operator (::). Names on the left side of the scope-resolution operator are always considered class names. The following example demonstrates how to declare a pointer to an object of type Account using the class keyword:

class Account *Checking = new class Account( Account );

The Account in the initializer (in parentheses) in the preceding statement has file scope; it is of type double.

Note The reuse of identifier names as shown in this example is considered poor programming style.

For more information about pointers, see Derived Types. For information about declaration and initialization of class objects, see Chapter 8, Classes. For information about using the new and delete free-store operators, see Chapter 11, Special Member Functions.


Scope of Formal Arguments to Functions

Formal arguments (arguments specified in function definitions) to functions are considered to be in the scope of the outermost block of the function body.


Program and Linkage

A program consists of one or more translation units linked together. Execution (conceptually) begins in the translation unit that contains the function main. (For more information on translation units, see Phases of Translation, in the Preprocessor Reference.) For more information about the main function, see Program Startup: the main Function.)


Types of Linkage

The way the names of objects and functions are shared between translation units is called “linkage.” These names can have:

  • Internal linkage, in which case they refer only to program elements inside their own translation units; they are not shared with other translation units.

    The same name in another translation unit may refer to a different object or a different class. Names with internal linkage are sometimes referred to as being “local” to their translation units.

    An example declaration of a name with internal linkage is:

    static int i;   // The static keyword ensures internal linkage.
  • External linkage, in which case they can refer to program elements in any translation unit in the program — the program element is shared among the translation units.

    The same name in another translation unit is guaranteed to refer to the same object or class. Names with external linkage are sometimes referred to as being “global.”

    An example declaration of a name with external linkage is:

    extern int i;
  • No linkage, in which case they refer to unique entities. The same name in another scope may not refer to the same object. An example is an enumeration. (Note, however, that you can pass a pointer to an object with no linkage. This makes the object accessible in other translation units.)


Linkage in Names with File Scope

The following linkage rules apply to names (other than typedef and enumerator names) with file scope:

  • If a name is explicitly declared as static, it has internal linkage and identifies a program element inside its own translation unit.

  • Enumerator names and typedef names have no linkage.

  • All other names with file scope have external linkage.

Microsoft Specific

  • If a function name with file scope is explicitly declared as inline, it has external linkage if it is instantiated or its address is referenced. Therefore, it is possible for a function with file scope to have either internal or external linkage.

END Microsoft Specific

A class has internal linkage if it:

  • Uses no C++ functionality (for example, member-access control, member functions, constructors, destructors, and so on).

  • Is not used in the declaration of another name that has external linkage. This constraint means that objects of class type that are passed to functions with external linkage cause the class to have external linkage.


Linkage in Names with Class Scope

The following linkage rules apply to names with class scope:

  • Static class members have external linkage.

  • Class member functions have external linkage.

  • Enumerators and typedef names have no linkage.

Microsoft Specific

  • Functions declared as friend functions must have external linkage. Declaring a static function as a friend generates an error.

END Microsoft Specific


Linkage in Names with Block Scope

The following linkage rules apply to names with block scope (local names):

  • Names declared as extern have external linkage unless they were previously declared as static.

  • All other names with block scope have no linkage.


Names with No Linkage

The only names that have no linkage are:

  • Function parameters.

  • Block-scoped names not declared as extern or static.

  • Enumerators.

  • Names declared in a typedef statement. An exception is when the typedef statement is used to provide a name for an unnamed class type. The name may then have external linkage if the class has external linkage. The following example shows a situation in which a typedef name has external linkage:
    typedef struct
{
    short x;
    short y;
} POINT;
extern int MoveTo( POINT pt );

    The typedef name, POINT, becomes the class name for the unnamed structure. It is then used to declare a function with external linkage.

Because typedef names have no linkage, their definitions can differ between translation units. Because the compilations take place discretely, there is no way for the compiler to detect these differences. As a result, errors of this kind are not detected until link time. Consider the following case:

// Translation unit 1
typedef int INT

INT myInt;
...

// Translation unit 2
typedef short INT

extern INT myInt;
...

The preceding code generates an “unresolved external” error at link time.

C++ functions can be defined only in file or class scope. The following example illustrates how to define functions and shows an erroneous function definition:

#include <iostream.h>

void ShowChar( char ch );    // Declare function ShowChar.

void ShowChar( char ch )     // Define function ShowChar.
{                            // Function has file scope.
   cout << ch;
}

struct Char                  // Define class Char.
{
    char Show();             // Declare Show function.
    char Get();              // Declare Get function.
    char ch;
};

char Char::Show()            // Define Show function
{                            //  with class scope.
    cout << ch;
    return ch;
}

void GoodFuncDef( char ch )  // Define GoodFuncDef
{                            //  with file scope.
    int BadFuncDef( int i )  // Erroneous attempt to
    {                        //  nest functions.
        return i * 7;
    }
    for( int i = 0; i < BadFuncDef( 2 ); ++i )
        cout << ch;
    cout << "\n";
}


Linkage to Non-C++ Functions

C functions and data can be accessed only if they are previously declared as having C linkage. However, they must be defined in a separately compiled translation unit.

Syntax

linkage-specification :

extern string-literal { declaration-listopt }
extern string-literal declaration

declaration-list :

declaration
declaration-list declaration

Microsoft C++ supports the strings "C" and "C++" in the string-literal field. The following example shows alternative ways to declare names that have C linkage:

// Declare printf with C linkage.
extern "C" int printf( const char *fmt, ... );

//  Cause everything in the header file "cinclude.h"
//   to have C linkage.
extern "C"
{
#include <cinclude.h>
}

//  Declare the two functions ShowChar and GetChar
//   with C linkage.
extern "C"
{
    char ShowChar( char ch );
    char GetChar( void );
}

//  Define the two functions ShowChar and GetChar
//   with C linkage.
extern "C" char ShowChar( char ch )
{
    putchar( ch );
    return ch;
}

extern "C" char GetChar( void )
{
    char ch;

    ch = getchar();
    return ch;
}

// Declare a global variable, errno, with C linkage.
extern "C" int errno;


Startup and Termination

Program startup and termination is facilitated by using two functions: main and exit. Other startup and termination code may be executed.


Program Startup: the main Function

A special function called main is the entry point to all C++ programs. This function is not predefined by the compiler; rather, it must be supplied in the program text. If you are writing code that adheres to the Unicode programming model, you can use the wide-character version of main, wmain. The declaration syntax for main is:

int main( );

or, optionally:

int main( int argc[ , char *argv[ ] [, char *envp[ ] ] ] );

The declaration syntax for wmain is as follows:

int wmain( );

or, optionally:

int wmain( int argc[ , wchar_t *argv[ ] [, wchar_t *envp[ ] ] ] );

Alternatively, the main and wmain functions can be declared as returning void (no return value). If you declare main or wmain as returning void, you cannot return an exit code to the parent process or operating system using a return statement; to return an exit code when main or wmain are declared as void, you must use the exit function.


Using wmain Instead of main

In the Unicode programming model, you can define a wide-character version of the main function. Use wmain instead of main if you want to write portable code that adheres to the Unicode specification.

You declare formal parameters to wmain using a similar format to main. You can then pass wide-character arguments and, optionally, a wide-character environment pointer to the program. The argv and envp parameters to wmain are of type wchar_t*.

If your program uses a main function, the multibyte-character environment is created by the operating system at program startup. A wide-character copy of the environment is created only when needed (for example, by a call to the _wgetenv or _wputenv functions). On the first call to _wputenv, or on the first call to _wgetenv if an MBCS environment already exists, a corresponding wide-character string environment is created and is then pointed to by the _wenviron global variable, which is a wide-character version of the _environ global variable. At this point, two copies of the environment (MBCS and Unicode) exist simultaneously and are maintained by the operating system throughout the life of the program.

Similarly, if your program uses a wmain function, an MBCS (ASCII) environment is created on the first call to _putenv or getenv, and is pointed to by the _environ global variable.

For more information on the MBCS environment, see Single-byte and Multibyte Character Sets in Chapter 2 of the Run-Time Library Reference.


Argument Definitions

The arguments in the prototype

int main( int argc[ , char *argv[ ] [, char *envp[ ] ] ] );

or

int wmain( int argc[ , wchar_t *argv[ ] [, wchar_t *envp[ ] ] ] );

allow convenient command-line parsing of arguments and, optionally, access to environment variables. The argument definitions are as follows:

argc

An integer that contains the count of arguments that follow in argv. The argc parameter is always greater than or equal to 1.

argv

An array of null-terminated strings representing command-line arguments entered by the user of the program. By convention, argv[0] is the command with which the program is invoked, argv[1] is the first command-line argument, and so on, until argv[argc], which is always NULL. See Customizing Command Line Processing for information on suprressing command-line processing.

The first command-line argument is always argv[1] and the last one is argv[argc – 1].

Microsoft Specific

envp

The envp array, which is a common extension in many UNIX® systems, is used in Microsoft C++. It is an array of strings representing the variables set in the user’s environment. This array is terminated by a NULL entry. See Customizing Command Line Processing for information on suprressing environment processing. This argument is ANSI compatible in C, but not in C++.

END Microsoft Specific

The following example shows how to use the argc, argv, and envp arguments to main:

#include <iostream.h>
#include <string.h>

void main( int argc, char *argv[], char *envp[] )
{
    int iNumberLines = 0;    // Default is no line numbers.

    // If more than .EXE filename supplied, and if the
    // /n command-line option is specified, the listing
    // of environment variables is line-numbered.

    if( argc == 2 && stricmp( argv[1], "/n" ) == 0 )
        iNumberLines = 1;

    // Walk through list of strings until a NULL is encountered.
    for( int i = 0; envp[i] != NULL; ++i )
    {
        if( iNumberLines )
            cout << i << ": " << envp[i] << "\n";
    }
}


Wildcard Expansion

Microsoft Specific

You can use wildcards — the question mark (?) and asterisk (*) — to specify filename and path arguments on the command line.

Command-line arguments are handled by a routine called _setargv. By default, _setargv expands wildcards into separate strings in the argv string array. If no matches are found for the wildcard argument, the argument is passed literally.

END Microsoft Specific


Parsing C++ Command-Line Arguments

Microsoft Specific

Microsoft C/C++ startup code uses the following rules when interpreting arguments given on the operating system command line:

  • Arguments are delimited by white space, which is either a space or a tab.

  • The caret character (^) is not recognized as an escape character or delimiter. The character is handled completely by the command-line parser in the operating system before being passed to the argv array in the program.

  • A string surrounded by double quotation marks ("string") is interpreted as a single argument, regardless of white space contained within. A quoted string can be embedded in an argument.

  • A double quotation mark preceded by a backslash ( \") is interpreted as a literal double quotation mark character (").

  • Backslashes are interpreted literally, unless they immediately precede a double quotation mark.

  • If an even number of backslashes is followed by a double quotation mark, one backslash is placed in the argv array for every pair of backslashes, and the double quotation mark is interpreted as a string delimiter.

  • If an odd number of backslashes is followed by a double quotation mark, one backslash is placed in the argv array for every pair of backslashes, and the double quotation mark is “escaped” by the remaining backslash, causing a literal double quotation mark (") to be placed in argv.

The following program demonstrates how command-line arguments are passed:

include <iostream.h>

void main( int argc,      // Number of strings in array argv
          char *argv[],   // Array of command-line argument strings
          char *envp[] )  // Array of environment variable strings
{
    int count;

    // Display each command-line argument.
    cout << "\nCommand-line arguments:\n";
    for( count = 0; count < argc; count++ )
         cout << "  argv[" << count << "]   "
                << argv[count] << "\n";
}

Table 2.2 shows example input and expected output, demonstrating the rules in the preceding list.

Table 2.2

Command-Line Input argv[1] argv[2] argv[3]
"abc" d e

abc

d

e

a\\\b d"e f"g h

a\\\b

de fg

h

a\\\"b c d

a\"b

c

d

a\\\\"b c" d e

a\\b c

d

e

END Microsoft Specific


Customizing C++ Command-Line Processing

Microsoft Specific

If your program does not take command-line arguments, you can save a small amount of space by suppressing use of the library routine that performs command-line processing. This routine is called _setargv and is described in Wildcard Expansion. To suppress its use, define a routine that does nothing in the file containing the main function, and name it _setargv. The call to _setargv is then satisfied by your definition of _setargv, and the library version is not loaded.

Similarly, if you never access the environment table through the envp argument, you can provide your own empty routine to be used in place of _setenvp, the environment-processing routine. Just as with the _setargv function, _setenvp must be declared as extern "C".

Your program might make calls to the spawn or exec family of routines in the C run-time library. If this is the case, you should not suppress the environment-processing routine, since this routine is used to pass an environment from the parent process to the child process.

END Microsoft Specific


main Function Restrictions

Several restrictions apply to the main function that do not apply to any other C++ functions. The main function:

  • Cannot be overloaded (see Chapter 12, Overloading).

  • Cannot be declared as inline.

  • Cannot be declared as static.

  • Cannot have its address taken.

  • Cannot be called.


Program Termination

In C++, there are several ways to exit a program:

  • Call the exit function.

  • Call the abort function.

  • Execute a return statement from main.


exit Function

The exit function, declared in the standard include file STDLIB.H, terminates a C++ program.

The value supplied as an argument to exit is returned to the operating system as the program’s return code or exit code. By convention, a return code of zero means that the program completed successfully.

Note You can use the constants EXIT_FAILURE and EXIT_SUCCESS, defined in STDLIB.H, to indicate success or failure of your program.

Issuing a return statement from the main function is equivalent to calling the exit function with the return value as its argument.

For more information, see exit in the Run-Time Library Reference.


abort Function

The abort function, also declared in the standard include file STDLIB.H, terminates a C++ program. The difference between exit and abort is that exit allows the C++ run-time termination processing to take place (global object destructors will be called), whereas abort terminates the program immediately. For more information, see abort in the Run-Time Library Reference.


return Statement

Issuing a return statement from main is functionally equivalent to calling the exit function. Consider the following example:

int main()
{
    exit( 3 );
    return 3;
}

The exit and return statements in the preceding example are functionally identical. However, C++ requires that functions that have return types other than void return a value. The return statement allows you to return a value from main.


Additional Startup Considerations

In C++, object construction and destruction can involve executing user code. Therefore, it is important to understand which initializations happen before entry to main and which destructors are invoked after exit from main. (For detailed information about construction and destruction of objects, see Constructors and Destructors in Chapter 11.)

The following initializations take place prior to entry to main:

  • Default initialization of static data to zero. All static data without explicit initializers are set to zero prior to executing any other code, including run-time initialization. Static data members must still be explicitly defined.

  • Initialization of global static objects in a translation unit. This may occur either before entry to main or before the first use of any function or object in the object’s translation unit.

Microsoft Specific

In Microsoft C++, global static objects are initialized before entry to main.

END Microsoft Specific

Global static objects that are mutually interdependent but in different translation units may cause incorrect behavior.


Additional Termination Considerations

You can terminate a C++ program by using exit, return, or abort. You can add exit processing using the atexit function. These are discussed in the following sections.


Using exit or return

When you call exit or execute a return statement from main, static objects are destroyed in the reverse order of their initialization. This example shows how such initialization and cleanup works:

#include <stdio.h>

class ShowData
{
public:
    // Constructor opens a file.
    ShowData( const char *szDev )
    {
        OutputDev = fopen( szDev, "w" );
    }

    // Destructor closes the file.
    ~ShowData() { fclose( OutputDev ); }

    // Disp function shows a string on the output device.
    void Disp( char *szData )
    {
        fputs( szData, OutputDev );
    }
private:
    FILE *OutputDev;
};

//  Define a static object of type ShowData. The output device
//   selected is "CON" -- the standard output device.
ShowData sd1 = "CON";
//  Define another static object of type ShowData. The output
//   is directed to a file called "HELLO.DAT"
ShowData sd2 = "hello.dat";

int main()
{
    sd1.Disp( "hello to default device\n" );
    sd2.Disp( "hello to file hello.dat\n" );

    return 0;
}

In the preceding example, the static objects sd1 and sd2 are created and initialized before entry to main. After this program terminates using the return statement, first sd2 is destroyed and then sd1. The destructor for the ShowData class closes the files associated with these static objects. (For more information about initialization, constructors, and destructors, see Chapter 11, Special Member Functions.)

Another way to write this code is to declare the ShowData objects with block scope, allowing them to be destroyed when they go out of scope:

int main()
{
    ShowData sd1, sd2( "hello.dat" );

    sd1.Disp( "hello to default device\n" );
    sd2.Disp( "hello to file hello.dat\n" );

    return 0;
}


Using atexit

With the atexit function, you can specify an exit-processing function that executes prior to program termination. No global static objects initialized prior to the call to atexit are destroyed prior to execution of the exit-processing function.


Using abort

Calling the abort function causes immediate termination. It bypasses the normal destruction process for initialized global static objects. It also bypasses any special processing that was specified using the atexit function.


C++ Storage Classes

Storage classes govern the lifetime, linkage, and treatment of objects and variables in C++. A given object can have only one storage class. This section discusses the C++ storage classes for data:

  • Automatic

  • Static

  • Register

  • External


Automatic

Objects and variables with automatic storage are local to a given instance of a block. In recursive or multithreaded code, automatic objects and variables are guaranteed to have different storage in different instances of a block. Microsoft C++ stores automatic objects and variables on the program’s stack.

Objects and variables defined within a block have auto storage unless otherwise specified using the extern or static keyword. Automatic objects and variables can be specified using the auto keyword, but explicit use of auto is unnecessary. Automatic objects and variables have no linkage.

Automatic objects and variables persist only until the end of the block in which they are declared.


Static

Objects and variables declared as static retain their values for the duration of the program’s execution. In recursive code, a static object or variable is guaranteed to have the same state in different instances of a block of code.

Objects and variables defined outside all blocks have static lifetime and external linkage by default. A global object or variable that is explicitly declared as static has internal linkage.

Static objects and variables persist for the duration of the program’s execution.


Register

Only function arguments and local variables can be declared with the register storage class.

Like automatic variables, register variables persist only until the end of the block in which they are declared.

The compiler does not honor user requests for register variables; instead, it makes its own register choices when global optimizations are on. However, all other semantics associated with the register keyword are honored by the compiler.


External

Objects and variables declared as extern declare an object that is defined in another translation unit or in an enclosing scope as having external linkage.

Declaration of const variables with the extern storage class forces the variable to have external linkage. An initialization of an extern const variable is allowed in the defining translation unit. Initializations in translation units other than the defining translation unit produce undefined results.

The following code shows two extern declarations, DefinedElsewhere (which refers to a name defined in a different translation unit) and DefinedHere (which refers to a name defined in an enclosing scope):

extern int DefinedElsewhere;        // Defined in another translation
                                    //  unit.
void main()
{
    int DefinedHere;
    {
       extern int DefinedHere;     // Refers to DefinedHere in
                                   //  the enclosing scope.
    }
}


Initialization of Objects

A local automatic object or variable is initialized every time the flow of control reaches its definition. A local static object or variable is initialized the first time the flow of control reaches its definition. Consider the following example, which defines a class that logs initialization and destruction of objects and then defines three objects, I1, I2, and I3:

#include <iostream.h>
#include <string.h>

// Define a class that logs initializations and destructions.
class InitDemo
{
public:
    InitDemo( const char *szWhat );
    ~InitDemo();
private:
    char *szObjName;
};

// Constructor for class InitDemo
InitDemo::InitDemo( const char *szWhat )
{
    if( szWhat != 0 && strlen( szWhat ) > 0 )
    {
        // Allocate storage for szObjName, then copy
        //  initializer szWhat into szObjName.
        szObjName = new char[ strlen( szWhat ) + 1 ];
        strcpy( szObjName, szWhat );
            cout << "Initializing: " << szObjName << "\n";
    }
    else
        szObjName = 0;
}

// Destructor for InitDemo
InitDemo::~InitDemo()
{
    if( szObjName != 0 )
    {
        cout << "Destroying: " << szObjName << "\n";
        delete szObjName;
    }
}

// Enter main function
void main()
{
    InitDemo I1( "Auto I1" );
    {
        cout << "In block.\n";
        InitDemo I2( "Auto I2" );
        static InitDemo I3( "Static I3" );
    }
    cout << "Exited block.\n";
}

The preceding code demonstrates how and when the objects I1, I2, and I3 are initialized and when they are destroyed. The output from the program is:

Initializing: Auto I1
In block.
Initializing: Auto I2
Initializing: Static I3
Destroying: Auto I2
Exited block.
Destroying: Auto I1
Destroying: Static I3

There are several points to note about the program.

First, I1 and I2 are automatically destroyed when the flow of control exits the block in which they are defined.

Second, in C++, it is not necessary to declare objects or variables at the beginning of a block. Furthermore, these objects are initialized only when the flow of control reaches their definitions. (I2 and I3 are examples of such definitions.) The output shows exactly when they are initialized.

Finally, static local variables such as I3 retain their values for the duration of the program but are destroyed as the program terminates.


Types

C++ supports three kinds of object types:

  • Fundamental types are built into the language (such as int, float, or double). Instances of these fundamental types are often called “variables.”

  • Derived types are new types derived from built-in types.

  • Class types are new types created by combining existing types. These are discussed in Chapter 8, Classes.


Fundamental Types

Fundamental types in C++ are divided into three categories: “integral,” “floating,” and “void.” Integral types are capable of handling whole numbers. Floating types are capable of specifying values that may have fractional parts.

The void type describes an empty set of values. No variable of type void can be specified — it is used primarily to declare functions that return no values or to declare “generic” pointers to untyped or arbitrarily typed data. Any expression can be explicitly converted or cast to type void. However, such expressions are restricted to the following uses:

  • An expression statement. (See Chapter 4, Expressions, for more information.)

  • The left operand of the comma operator. (See Comma Operator in Chapter 4 for more information.)

  • The second or third operand of the conditional operator (? :). (See Expressions with the Conditional Operator in Chapter 4 for more information.)

Table 2.3 explains the restrictions on type sizes. These restrictions are independent of the Microsoft implementation.

Table 2.3 Fundamental Types of the C++ Language

Category | Type | Contents
Integral | char | Type char is an integral type that usually contains members of the execution character set — in Microsoft C++, this is ASCII.
 |  | The C++ compiler treats variables of type char, signed char, and unsigned char as having different types. Variables of type char are promoted to int as if they are type signed char by default, unless the /J compilation option is used. In this case they are treated as type unsigned char and are promoted to int without sign extension.
 | short | Type short int (or simply short) is an integral type that is larger than or equal to the size of type char, and shorter than or equal to the size of type int.
 |  | Objects of type short can be declared as signed short or unsigned short. Signed short is a synonym for short.
 | int | Type int is an integral type that is larger than or equal to the size of type short int, and shorter than or equal to the size of type long.
 |  | Objects of type int can be declared as signed int or unsigned int. Signed int is a synonym for int.
 | __int n | Sized integer, where n is the size, in bits, of the integer variable. The value of n can be 8, 16, 32, or 64.
 | long | Type long (or long int) is an integral type that is larger than or equal to the size of type int.
 |  | Objects of type long can be declared as signed long or unsigned long. Signed long is a synonym for long.
Floating | float | Type float is the smallest floating type.
 | double | Type double is a floating type that is larger than or equal to type float, but shorter than or equal to the size of type long double.1
 | long double1 | Type long double is a floating type that is equal to type double.

1 The representation of long double and double is identical. However, long double and double are separate types.

Microsoft Specific

Table 2.4 lists the amount of storage required for fundamental types in Microsoft C++.

Table 2.4 Sizes of Fundamental Types

Type | Size
char, unsigned char, signed char | 1 byte
short, unsigned short | 2 bytes
int, unsigned int | 4 bytes
long, unsigned long | 4 bytes
float | 4 bytes
double | 8 bytes
long double1 | 8 bytes

1 The representation of long double and double is identical. However, long double and double are separate types.

For more information about type conversion, see Chapter 3, Standard Conversions.

END Microsoft Specific


C++ Sized Integer Types

Microsoft C++ also supports sized integer types. You can declare 8-, 16-, 32-, or 64-bit integer variables by using the __int n type specifier, where n is the size, in bits, of the integer variable. The value of n can be 8, 16, 32, or 64. The following example declares one variable for each of these types of sized integers:

__int8 nSmall;      // Declares 8-bit integer
__int16 nMedium;   // Declares 16-bit integer
__int32 nLarge;      // Declares 32-bit integer
__int64 nHuge;      // Declares 64-bit integer

The types __int8, __int16, and __int32, are synonyms for the ANSI types that have the same size, and are useful for writing portable code that behaves identically across multiple platforms. Note that the __int8 data type is synonymous with type char, __int16 is synonymous with type short, and __int32 is synonymous with type int. The __int64 data type has no ANSI equivalent.

Since __int8, __int16, and __int32 are considered synonyms by the compiler, care should be taken when using these types as arguments to overloaded function calls. For example, the following C++ code will generate a compiler error:

void MyFunc( __int8 ) {}
void MyFunc( char ) {}

void main()
{
    __int8 newVal;
    char MyChar;
    MyFunc( MyChar );      // Ambiguous function calls;
    MyFunc( newVal );      // char is synonymous with __int8.
}


Derived Types

Derived types are new types that can be used in a program, and can include directly derived types and composed derivative types.


Directly Derived Types

New types derived directly from existing types are types that point to, refer to, or (in the case of functions) transform type data to return a new type.

  • Arrays of Variables or Objects

  • Functions

  • Pointers of a Given Type

  • References to Objects

  • Constants

  • Pointers to Class Members

Arrays of Variables or Objects

Arrays of variables or objects can contain a specified number of a particular type. For example, an array derived from integers is an array of type int. The following code sample declares and defines an array of 10 int variables and an array of 5 objects of class SampleClass:

int         ArrayOfInt[10];
SampleClass aSampleClass[5];

Functions

Functions take zero or more arguments of given types and return objects of a specified type (or return nothing, if the function has a void return type).

Pointers of a Given Type

Pointers to variables or objects select an object in memory. The object can be global, local (or stack-frame), or dynamically allocated. Pointers to functions of a given type allow a program to defer selection of the function used on a particular object or objects until run time. The following example shows a definition of a pointer to a variable of type char:

char *szPathStr;

References to Objects

References to objects provide a convenient way to access objects by reference but use the same syntax required to access objects by value. The following example demonstrates how to use references as arguments to functions and as return types of functions:

BigClassType &func( BigClassType &objname )
{
    objname.DoSomething();    // Note that member-of operator(.)
                              //  is used.
    objname.SomeData = 7;     // Data passed by non-const
                              //  reference is modifiable.
    return objname;
}

The important points about passing objects to a function by reference are:

  • The syntax for accessing members of class, struct, and union objects is the same as if they were passed by value: the member-of operator (.).

  • The objects are not copied prior to the function call; their addresses are passed. This can reduce the overhead of the function call.

Additionally, functions that return a reference need only accept the address of the object to which they refer, instead of a copy of the whole object.

Although the preceding example describes references only in the context of communication with functions, references are not constrained to this use. Consider, for example, a case where a function needs to be an l-value — a common requirement for overloaded operators:

class Vector
{
public:
    Point &operator[]( int nSubscript ); // Function returns a
                                         //  reference type
    ...
};

The preceding declaration specifies a user-defined subscript operator for class Vector. In an assignment statement, two possible conditions occur:

Vector v1;
int    i;
Point p;
v1[7] = p;   // Vector used as an l-value
p = v1[7];   // Vector used as an r-value

The latter case, where v1[7] is used as an r-value, can be implemented without use of references. However, the former case, where v1[7] is used as an l-value, cannot be implemented easily without functions that are of reference type. Conceptually, the last two statements in the preceding example translate to the following code:

v1.operator[]( 7 ) = 3;    // Vector used as an l-value
i = v1.operator[]( 7 );    // Vector used as an r-value

When viewed in this way, it is easier to see that the first statement must be an l-value to be semantically correct on the left side of the assignment statement.

For more information about overloading, and about overloaded operators in particular, see Overloaded Operators in Chapter 12.

You can also use references to declare a const reference to a variable or object. A reference declared as const retains the efficiency of passing an argument by reference, while preventing the called function from modifying the original object. Consider the following code:

// IntValue is a const reference.
void PrintInt( const int &IntValue )
{
    printf( "%d\n", IntValue );
}

Reference initialization is different from assignment to a variable of reference type. Consider the following code:

int i = 7;
int j = 5;

// Reference initialization
int &ri = i;  // Initialize ri to refer to i.
int &rj = j;  // Initialize rj to refer to j.

// Assignment
ri = 3;       // i now equal to 3.
rj = 12;      // j now equal to 12.
ri = rj;      // i now equals j (12).

C++ Constants

See Literals in Chapter 1 for more information about the various kinds of constants allowed in C++.

Pointers to Class Members

These pointers define a type that points to a class member of a particular type. Such a pointer can be used by any object of the class type or any object of a type derived from the class type.

Use of pointers to class members enhances the type safety of the C++ language. Three new operators and constructs are used with pointers to members, as shown in Table 2.5.

Table 2.5 Operators and Constructs Used with Pointers to Members

Operator or
Construct
Syntax
Use
::* type::*ptr-name Declaration of pointer to member. The type specifies the class name, and ptr-name specifies the name of the pointer to member. Pointers to members can be initialized. For example:
MyType::*pMyType = &MyType::i;
.* obj-name.*ptr-name Dereference a pointer to a member using an object or object reference. For example:
int j = Object.*pMyType;
–>* obj-ptr–>*ptr-name Dereference a pointer to a member using a pointer to an object. For example:
int j = pObject->*pMyType;

Consider this example that defines a class AClass and the derived type pDAT, which points to the member I1:

#include <iostream.h>

// Define class AClass.
class AClass
{
public:
    int I1;
    Show() { cout << I1 << "\n"; }
};

// Define a derived type pDAT that points to I1 members of
// objects of type AClass.
int AClass::*pDAT = &AClass::I1;

void main()
{
    AClass aClass;             // Define an object of type AClass.
    AClass *paClass = &aClass;  // Define a pointer to that object.

    int i;

    aClass.*pDAT = 7777;      // Assign to aClass::I1 using .* operator.
    aClass.Show();

    i = paClass->*pDAT;       // Dereference a pointer
                              //  using ->* operator.
    cout << i << "\n";
}

The pointer to member pDAT is a new type derived from class AClass. It is more strongly typed than a “plain” pointer to int because it points only to int members of class AClass (in this case, I1). Pointers to static members are plain pointers rather than pointers to class members. Consider the following example:

class HasStaticMember
{
public:
    static int SMember;
};
int HasStaticMember::SMember = 0;

int *pSMember = &HasStaticMember::SMember;

Note that the type of the pointer is “pointer to int,” not “pointer to HasStaticMember::int.”

Pointers to members can refer to member functions as well as member data. Consider the following code:

#include <stdio.h>

// Declare a base class, A, with a virtual function, Identify.
// (Note that in this context, struct is the same as class.)
struct A
{
    virtual void Identify() = 0; // No definition for class A.
};

// Declare a pointer to the Identify member function.
void (A::*pIdentify)() = &A::Identify;

// Declare class B derived from class A.
struct B : public A
{
    void Identify();
};

// Define Identify functions for classe B
void B::Identify()
{
    printf( "Identification is B::Identify\n" );
}

void main()
{
    B  BObject;          // Declare objects of type B
    A *pA;               // Declare pointer to type A.

    pA = &BObject;       // Make pA point to an object of type B.
    (pA->*pIdentify)();  // Call Identify function through pointer
                         //  to member pIdentify.
}

The output from this program is:

Identification is B::Identify

The function is called through a pointer to type A. However, because the function is a virtual function, the correct function for the object to which pA refers is called.


Composed Derivative Types

This section describes the following composed derivative types:

  • Classes

  • Structures

  • Unions

Information about aggregate types and initialization of aggregate types can be found in Initializing Aggregates in Chapter 7.

C++ Classes

Classes are a composite group of member objects, functions to manipulate these members, and (optionally) access-control specifications to member objects and functions.

By grouping composite groups of objects and functions in classes, C++ enables programmers to create derivative types that define not only data but also the behavior of objects.

Class members default to private access and private inheritance. Classes are covered in Chapter 8, Classes, access control is covered in Chapter 10, Member-Access Control.

C++ Structures

C++ structures are the same as classes, except that all member data and functions default to public access, and inheritance defaults to public inheritance.

For more information about access control, see Chapter 10, Member-Access Control.

C++ Unions

Unions enable programmers to define types capable of containing different kinds of variables in the same memory space. The following code shows how you can use a union to store several different types of variables:

//  Declare a union that can hold data of types char, int,
//    or char *.
union ToPrint
{
    char   chVar;
    int    iVar;
    char  *szVar;
};

// Declare an enumerated type that describes what type to print.
enum PrintType { CHAR_T, INT_T, STRING_T };

void Print( ToPrint Var, PrintType Type )
{
    switch( Type )
    {
    case CHAR_T:
        printf( "%c", Var.chVar );
        break;
    case INT_T:
        printf( "%d", Var.iVar );
        break;
    case STRING_T:
        printf( "%s", Var.szVar );
        break;
    }
}


C++ Type Names

Synonyms for both fundamental and derived types can be defined using the typedef keyword. The following code illustrates the use of typedef:

typedef unsigned char BYTE;   // 8-bit unsigned entity.
typedef BYTE *        PBYTE;  // Pointer to BYTE.

BYTE Ch;                      // Declare a variable of type BYTE.
PBYTE pbCh;                   // Declare a pointer to a BYTE
                              //  variable.

The preceding example shows uniform declaration syntax for the fundamental type unsigned char and its derivative type unsigned char *. The typedef construct is also helpful in simplifying declarations. A typedef declaration defines a synonym, not a new independent type. The following example declares a type name (PVFN) representing a pointer to a function that returns type void. The advantage of this declaration is that, later in the program, an array of these pointers is declared very simply.

// Prototype two functions.
void func1();
void func2();

//  Define PVFN to represent a pointer to a function that
//   returns type void.
typedef void (*PVFN)();

...

// Declare an array of pointers to functions.
PVFN pvfn[] = { func1, func2 };

// Invoke one of the functions.
(*pvfn[1])();


L-Values and R-Values

Expressions in C++ can evaluate to “l-values” or “r-values.” L-values are expressions that evaluate to a type other than void and that designate a variable.

L-values appear on the left side of an assignment statement (hence the “l” in l-value). Variables that would normally be l-values can be made nonmodifiable by using the const keyword; these cannot appear on the left of an assignment statement. Reference types are always l-values.

The term r-value is sometimes used to describe the value of an expression and to distinguish it from an l-value. All l-values are r-values but not all r-values are l-values.

Some examples of correct and incorrect usages are:

i = 7;            // Correct. A variable name, i, is an l-value.
7 = i;            // Error. A constant, 7, is an r-value.
j * 4 = 7;        // Error. The expression j * 4 yields an r-value.
*p = i;           // Correct. A dereferenced pointer is an l-value.
const int ci = 7; // Declare a const variable.
ci = 9;           // ci is a nonmodifiable l-value, so the
                  //  assignment causes an error message to
                  //  be generated.
((i < 3) ? i : j) = 7; // Correct. Conditional operator (? :)
                       //  returns an l-value.

Note The examples in this section illustrate correct and incorrect usage when operators are not overloaded. By overloading operators, you can make an expression such as j * 4 an l-value.


Numerical Limits

The two standard include files, LIMITS.H and FLOAT.H, define the “numerical limits,” or minimum and maximum values that a variable of a given type can hold. These minimums and maximums are guaranteed to be portable to any C++ compiler that uses the same data representation as ANSI C. The LIMITS.H include file defines the numerical limits for integral types, and FLOAT.H defines the numerical limits for floating types.


C++ Integer Limits

Microsoft Specific

The limits for integer types are listed in Table 2.6. These limits are also defined in the standard header file LIMITS.H.

Table 2.6 Limits on Integer Constants

Constant | Meaning | Value
CHAR_BIT | Number of bits in the smallest variable that is not a bit field. | 8
SCHAR_MIN | Minimum value for a variable of type signed char. | –128
SCHAR_MAX | Maximum value for a variable of type signed char. | 127
UCHAR_MAX | Maximum value for a variable of type unsigned char. | 255 (0xff)
CHAR_MIN | Minimum value for a variable of type char. | –128; 0 if /J option used
CHAR_MAX | Maximum value for a variable of type char. | 127; 255 if /J option used
MB_LEN_MAX | Maximum number of bytes in a multicharacter constant. | 2
SHRT_MIN | Minimum value for a variable of type short. | –32768
SHRT_MAX | Maximum value for a variable of type short. | 32767
USHRT_MAX | Maximum value for a variable of type unsigned short. | 65535 (0xffff)
INT_MIN | Minimum value for a variable of type int. | –2147483647 – 1
INT_MAX | Maximum value for a variable of type int. | 2147483647
UINT_MAX | Maximum value for a variable of type unsigned int. | 4294967295 (0xffffffff)
LONG_MIN | Minimum value for a variable of type long. | –2147483647 – 1
LONG_MAX | Maximum value for a variable of type long. | 2147483647
ULONG_MAX | Maximum value for a variable of type unsigned long. | 4294967295 (0xffffffff)

If a value exceeds the largest integer representation, the Microsoft compiler generates an error.

END Microsoft Specific


Floating Limits

Microsoft Specific

Table 2.7 lists the limits on the values of floating-point constants. These limits are also defined in the standard header file FLOAT.H.

Table 2.7 Limits on Floating-Point Constants

Constant | Meaning | Value
FLT_DIG DBL_DIG LDBL_DIG | Number of digits, q, such that a floating-point number with q decimal digits can be rounded into a floating-point representation and back without loss of precision. | 6 15 15
FLT_EPSILON DBL_EPSILON LDBL_EPSILON | Smallest positive number x, such that x + 1.0 is not equal to 1.0. | 1.192092896e–07F 2.2204460492503131e–016 2.2204460492503131e–016
FLT_GUARD |  | 0
FLT_MANT_DIG DBL_MANT_DIG LDBL_MANT_DIG | Number of digits in the radix specified by FLT_RADIX in the floating-point significand. The radix is 2; hence these values specify bits. | 24 53 53
FLT_MAX DBL_MAX LDBL_MAX | Maximum representable floating-point number. | 3.402823466e+38F 1.7976931348623158e+308 1.7976931348623158e+308
FLT_MAX_10_EXP DBL_MAX_10_EXP LDBL_MAX_10_EXP | Maximum integer such that 10 raised to that number is a representable floating-point number. | 38 308 308
FLT_MAX_EXP DBL_MAX_EXP LDBL_MAX_EXP | Maximum integer such that FLT_RADIX raised to that number is a representable floating- point number. | 128 1024 1024
FLT_MIN DBL_MIN LDBL_MIN | Minimum positive value. | 1.175494351e–38F 2.2250738585072014e–308 2.2250738585072014e–308
FLT_MIN_10_EXP DBL_MIN_10_EXP LDBL_MIN_10_EXP | Minimum negative integer such that 10 raised to that number is a representable floating- point number. | –37 –307 –307
FLT_MIN_EXP DBL_MIN_EXP LDBL_MIN_EXP | Minimum negative integer such that FLT_RADIX raised to that number is a representable floating-point number. | –125 –1021 –1021
FLT_NORMALIZE |  | 0
FLT_RADIX _DBL_RADIX _LDBL_RADIX | Radix of exponent representation. | 2 2 2
FLT_ROUNDS _DBL_ROUNDS _LDBL_ROUNDS | Rounding mode for floating-point addition. | 1 (near) 1 (near) 1 (near)

Note that the information in Table 2.7 may differ in future versions of the product.

END Microsoft Specific


Standard Conversions

The C++ language defines conversions between its fundamental types. It also defines conversions for pointer, reference, and pointer-to-member derived types. These conversions are called “standard conversions.” (For more information about types, standard types, and derived types, see Types in Chapter 2.)

This chapter discusses the following standard conversions:

  • Integral promotions

  • Integral conversions

  • Floating conversions

  • Floating and integral conversions

  • Arithmetic conversions

  • Pointer conversions

  • Reference conversions

  • Pointer-to-member conversions

Note User-defined types can specify their own conversions. Conversion of user-defined types is covered in Constructors and Conversions in Chapter 11.

The following code causes conversions (in this example, integral promotions):

long  lnum1, lnum2;
int   inum;

// inum promoted to type long prior to assignment.
lnum1 = inum;

// inum promoted to type long prior to multiplication.
lnum2 = inum * lnum2;

Note The result of a conversion is an l-value only if it produces a reference type. For example, a user-defined conversion declared as

operator int&()

returns a reference and is an l-value. However, a conversion declared as

operator int()

returns an object and is not an l-value.


Integral Promotions

Objects of an integral type can be converted to another wider integral type (that is, a type that can represent a larger set of values). This widening type of conversion is called “integral promotion.” With integral promotion, you can use the following in an expression wherever another integral type can be used:

  • Objects, literals, and constants of type char and short int

  • Enumeration types

  • int bit fields

  • Enumerators

C++ promotions are “value-preserving.” That is, the value after the promotion is guaranteed to be the same as the value before the promotion. In value-preserving promotions, objects of shorter integral types (such as bit fields or objects of type char) are promoted to type int if int can represent the full range of the original type. If int cannot represent the full range of values, then the object is promoted to type unsigned int. Although this strategy is the same as that used by ANSI C, value-preserving conversions do not preserve the “signedness” of the object.

Value-preserving promotions and promotions that preserve signedness normally produce the same results. However, they can produce different results if the promoted object is one of the following:

  • An operand of /, %, /=, %=, <, <=, >, or >=

    These operators rely on sign for determining the result. Therefore, value-preserving and sign-preserving promotions produce different results when applied to these operands.

  • The left operand of >> or >>=

    These operators treat signed and unsigned quantities differently when performing a shift operation. For signed quantities, shifting a quantity right causes the sign bit to be propagated into the vacated bit positions. For unsigned quantities, the vacated bit positions are zero-filled.

  • An argument to an overloaded function or operand of an overloaded operator that depends on the signedness of the type of that operand for argument matching. (See Overloaded Operators in Chapter 12 for more about defining overloaded operators.)


Integral Conversions

Integral conversions are performed between integral types. The integral types are char, int, and long (and the short, signed, and unsigned versions of these types).

This section describes the following types of integral conversions:

  • Converting signed to unsigned

  • Converting unsigned to signed

  • Standard conversion


Converting Signed to Unsigned

Objects of signed integral types can be converted to corresponding unsigned types. When these conversions occur, the actual bit pattern does not change; however, the interpretation of the data changes. Consider this code:

#include <iostream.h>

void main()
{
    short  i = -3;
    unsigned short u;

    cout << (u = i) << "\n";
}

The following output results:

65533

In the preceding example, a signed short, i, is defined and initialized to a negative number. The expression (u = i) causes i to be converted to an unsigned short prior to the assignment to u.


Converting Unsigned to Signed

Objects of unsigned integral types can be converted to corresponding signed types. However, such a conversion can cause misinterpretation of data if the value of the unsigned object is outside the range representable by the signed type, as demonstrated in the following example:

#include <iostream.h>

void main()
{
 short  i;
 unsigned short u = 65533;

 cout << (i = u) << "\n";
}

The following output results:

-3

In the preceding example, u is an unsigned short integral object that must be converted to a signed quantity to evaluate the expression (i = u). Because its value cannot be properly represented in a signed short, the data is misinterpreted as shown.


Standard Conversion

Objects of integral types can be converted to shorter signed or unsigned integral types. Such a conversion is called “standard conversion.” It can result in loss of data if the value of the original object is outside the range representable by the shorter type.

Note The compiler issues a high-level warning when a conversion to a shorter type takes place.


Floating Conversions

An object of a floating type can be safely converted to a more precise floating type — that is, the conversion causes no loss of significance. For example, conversions from float to double or from double to long double are safe, and the value is unchanged.

An object of a floating type can also be converted to a less precise type, if it is in a range representable by that type. (See Floating Limits in Chapter 2 for the ranges of floating types.) If the original value cannot be represented precisely, it can be converted to either the next higher or the next lower representable value. If no such value exists, the result is undefined. Consider the following example:

cout << (float)1E300 << endl;

The maximum value representable by type float is 3.402823466E38 — a much smaller number than 1E300. Therefore, the number is converted to infinity, and the result is 1.#INF.


Floating and Integral Conversions

Certain expressions can cause objects of floating type to be converted to integral types, or vice versa.

This section describes the following types of floating and integral conversions:

  • Floating to integral

  • Integral to floating


Floating to Integral

When an object of floating type is converted to an integral type, the fractional part is truncated. No rounding takes place in the conversion process. Truncation means that a number like 1.3 is converted to 1, and –1.3 is converted to –1.


Integral to Floating

When an object of integral type is converted to a floating type and the original value cannot be represented exactly, the result is either the next higher or the next lower representable value.


Arithmetic Conversions

Many binary operators (discussed in Expressions with Binary Operators in Chapter 4) cause conversions of operands and yield results the same way. The way these operators cause conversions is called “usual arithmetic conversions.” Arithmetic conversions of operands of different types are performed as shown in Table 3.1.

Table 3.1 Conditions for Type Conversion

Conditions Met | Conversion
Either operand is of type long double. | Other operand is converted to type long double.
Preceding condition not met and either operand is of type double. | Other operand is converted to type double.
Preceding conditions not met and either operand is of type float. | Other operand is converted to type float.
Preceding conditions not met (none of the operands are of floating types). Integral promotions are performed on the operands as follows:
  • If either operand is of type unsigned long, the other operand is converted to type unsigned long.

  • If preceding condition not met, and if either operand is of type long and the other of type unsigned int, both operands are converted to type unsigned long.

  • If the preceding two conditions are not met, and if either operand is of type long, the other operand is converted to type long.

  • If the preceding three conditions are not met, and if either operand is of type unsigned int, the other operand is converted to type unsigned int.

  • If none of the preceding conditions are met, both operands are converted to type int.

The following code illustrates the conversion rules described in Table 3.1:

float   fVal;
double  dVal;
int   iVal;
unsigned long ulVal;

dVal = iVal * ulVal; // iVal converted to unsigned long;
                     // result of multiplication converted to double.

dVal = ulVal + fVal; // ulVal converted to float;
                     // result of addition converted to double.

The first statement in the preceding example shows multiplication of two integral types, iVal and ulVal. The condition met is that neither operand is of floating type and one operand is of type unsigned int. Therefore, the other operand, iVal, is converted to type unsigned int. The result is assigned to dVal. The condition met is that one operand is of type double; therefore, the unsigned int result of the multiplication is converted to type double.

The second statement in the preceding example shows addition of a float and an integral type, fVal and ulVal. The ulVal variable is converted to type float (third condition in Table 3.1). The result of the addition is converted to type double (second condition in Table 3.1) and assigned to dVal.


Pointer Conversions

Pointers can be converted during assignment, initialization, comparison, and other expressions. This section describes the following pointer conversion:

  • Null pointers

  • Pointers to type void

  • Pointers to objects

  • Pointers to functions

  • Pointers to classes

  • Expressions

  • Pointers modified by const or volatile


Null Pointers

An integral constant expression that evaluates to zero, or such an expression cast to type void *, is converted to a pointer called the “null pointer.” This pointer is guaranteed to compare unequal to a pointer to any valid object or function (except for pointers to based objects, which can have the same offset and still point to different objects).


Pointers to Type void

Pointers to type void can be converted to pointers to any other type, but only with an explicit type cast (unlike in C). (See Expressions with Explicit Type Conversions in Chapter 4 for more information about type casts.) A pointer to any type can be converted implicitly to a pointer to type void.

A pointer to an incomplete object of a type can be converted to a pointer to void (implicitly) and back (explicitly). The result of such a conversion is equal to the value of the original pointer. An object is considered incomplete if it is declared, but there is insufficient information available to determine its size or base class.


Pointers to Objects

A pointer to any object that is not const or volatile can be implicitly converted to a pointer of type void *.


Pointers to Functions

A pointer to a function can be converted to type void *, if type void * is large enough to hold that pointer.


Pointers to Classes

There are two cases in which a pointer to a class can be converted to a pointer to a base class.

The first case is when the specified base class is accessible and the conversion is unambiguous. (See Multiple Base Classes in Chapter 9 for more information about ambiguous base-class references.)

Whether a base class is accessible depends on the kind of inheritance used in derivation. Consider the inheritance illustrated in Figure 3.1.

Figure 3.1 Inheritance Graph for Illustration of Base-Class Accessibility

Table 3.2 shows the base-class accessibility for the situation illustrated in Figure 3.1.

Table 3.2 Base-Class Accessibility

Type of Function | Derivation | Conversion from B* to A* Legal?
External (not class-scoped) function | Private | No
 | Protected | No
 | Public | Yes
B member function (in B scope) | Private | Yes
 | Protected | Yes
 | Public | Yes
C member function (in C scope) | Private | No
 | Protected | Yes
 | Public | Yes

The second case in which a pointer to a class can be converted to a pointer to a base class is when you use an explicit type conversion. (See Expressions with Explicit Type Conversions in Chapter 4 for more information about explicit type conversions.)

The result of such a conversion is a pointer to the “subobject,” the portion of the object that is completely described by the base class.

The following code defines two classes, A and B, where B is derived from A. (For more information on inheritance, see Chapter 9, Derived Classes.) It then defines bObject, an object of type B, and two pointers (pA and pB) that point to the object.

class A
{
public:
    int AComponent;
    int AMemberFunc();
};

class B : public A
{
public:
    int BComponent;
    int BMemberFunc();
};
B bObject;
A *pA = &bObject;
B *pB = &bObject;

pA->AMemberFunc();   // OK in class A
pB->AMemberFunc();   // OK: inherited from class A
pA->BMemberFunc();   // Error: not in class A

The pointer pA is of type A *, which can be interpreted as meaning “pointer to an object of type A.” Members of bObject (such as BComponent and BMemberFunc) are unique to type B and are therefore inaccessible through pA. The pA pointer allows access only to those characteristics (member functions and data) of the object that are defined in class A.


Pointer Expressions

Any expression with an array type can be converted to a pointer of the same type. The result of the conversion is a pointer to the first array element. The following example demonstrates such a conversion:

char szPath[_MAX_PATH]; // Array of type char.
char *pszPath = szPath; // Equals &szPath[0].

An expression that results in a function returning a particular type is converted to a pointer to a function returning that type, except when:

  • The expression is used as an operand to the address-of operator (&).

  • The expression is used as an operand to the function-call operator.


Pointers Modified by const or volatile

C++ does not supply a standard conversion from a const or volatile type to a type that is not const or volatile. However, any sort of conversion can be specified using explicit type casts (including conversions that are unsafe).

Note C++ pointers to members, except pointers to static members, are different from normal pointers and do not have the same standard conversions. Pointers to static members are normal pointers and have the same conversions as normal pointers. (See Pointers to Class Members in Chapter 2 for more information.)


Reference Conversions

A reference to a class can be converted to a reference to a base class in the following cases:

  • The specified base class is accessible (as defined in Pointers to Classes).

  • The conversion is unambiguous. (See Multiple Base Classes in Chapter 9 for more information about ambiguous base-class references.)

The result of the conversion is a pointer to the subobject that represents the base class.

For more information about references, see References to Objects in Chapter 2.


Pointer-to-Member Conversions

Pointers to class members can be converted during assignment, initialization, comparison, and other expressions. This section describes the following pointer-to-member conversions:

  • Integral constant expressions

  • Pointers to base-class members


Integral Constant Expressions

An integral constant expression that evaluates to zero is converted to a pointer called the “null pointer.” This pointer is guaranteed to compare unequal to a pointer to any valid object or function (except for pointers to based objects, which can have the same offset and still point to different objects).

The following code illustrates the definition of a pointer to member i in class A. The pointer, pai, is initialized to 0, which is the null pointer.

class A
{
public:
 int i;
};

int A::*pai = 0;


Pointers to Base-Class Members

A pointer to a member of a base class can be converted to a pointer to a member of a class derived from it, when the following conditions are met:

  • The inverse conversion, from pointer to derived class to base-class pointer, is accessible.

  • The derived class does not inherit virtually from the base class.

When the left operand is a pointer to member, the right operand must be of pointer-to-member type or be a constant expression that evaluates to 0. This assignment is valid only in the following cases:

  • The right operand is a pointer to a member of the same class as the left operand.

  • The left operand is a pointer to a member of a class derived publicly and unambiguously from the class of the right operand.


Expressions

This chapter describes C++ expressions. Expressions are sequences of operators and operands that are used for one or more of these purposes:

  • Computing a value from the operands.

  • Designating objects or functions.

  • Generating “side effects.” (Side effects are any actions other than the evaluation of the expression — for example, modifying the value of an object.)

In C++, operators can be overloaded and their meanings can be user-defined. However, their precedence and the number of operands they take cannot be modified. This chapter describes the syntax and semantics of operators as they are supplied with the language, not overloaded. The following topics are included:

  • Types of expressions

  • Semantics of expressions

(For more information about overloaded operators, see Overloaded Operators, in Chapter 12.)

Note Operators for built-in types cannot be overloaded; their behavior is predefined.


Types of Expressions

C++ expressions are divided into several categories:

  • Primary expressions. These are the building blocks from which all other expressions are formed.

  • Postfix expressions. These are primary expressions followed by an operator — for example, the array subscript or postfix increment operator.

  • Expressions formed with unary operators. Unary operators act on only one operand in an expression.

  • Expressions formed with binary operators. Binary operators act on two operands in an expression.

  • Expressions with the conditional operator. The conditional operator is a ternary operator — the only such operator in the C++ language — and takes three operands.

  • Constant expressions. Constant expressions are formed entirely of constant data.

  • Expressions with explicit type conversions. Explicit type conversions, or “casts,” can be used in expressions.

  • Expressions with pointer-to-member operators.

  • Casting. Type-safe “casts” can be used in expressions.

  • Run-Time Type Information. Determine the type of an object during program execution.


C++ Primary Expressions

Primary expressions are the building blocks of more complex expressions. They are literals, names, and names qualified by the scope-resolution operator (::).

Syntax

primary-expression :

literal
this
:: identifier
:: operator-function-name
:: qualified-name
( expression )
name

A literal is a constant primary expression. Its type depends on the form of its specification. See Literals for complete information about specifying literals.

The this keyword is a pointer to a class object. It is available within nonstatic member functions and points to the instance of the class for which the function was invoked. The this keyword cannot be used outside the body of a class-member function.

The type of the this pointer is type *const (where type is the class name) within functions not specifically modifying the this pointer. The following example shows member function declarations and the types of this:

class Example
{
public:
    void Func();          //  * const this
    void Func() const;    //  const * const this
    void Func() volatile; //  volatile * const this
};

See Type of this Pointer for more information about modifying the type of the this pointer.

The scope-resolution operator (::) followed by an identifier, operator-function-name, or qualified-name constitutes a primary expression. The type of this expression is determined by the declaration of the identifier, operator-function-name, or name. It is an l-value if the declaring name is an l-value. The scope-resolution operator allows a global name to be referred to, even if that name is hidden in the current scope. See Scope for an example of how to use the scope-resolution operator.

An expression enclosed in parentheses is a primary expression whose type and value are identical to those of the unparenthesized expression. It is an l-value if the unparenthesized expression is an l-value.


Names

In the C++ syntax for primary-expression, a name is a primary expression that can appear only after the member-selection operators (. or –>), and names the member of a class.

Syntax

name :

identifier
operator-function-name
conversion-function-name
~ class-name
qualified-name

Any identifier that has been declared is a name.

An operator-function-name is a name that is declared in the form

operator operator-name( argument1 [ , argument2] );

See Overloaded Operators for more information about declaration of operator-function-name.

A conversion-function-name is a name that is declared in the form

operator type-name( )

Note You can supply a derivative type name such as char * in place of the type-name when declaring a conversion function.

Conversion functions supply conversions to and from user-defined types. For more information about user-supplied conversions, see Conversion Functions.

A name declared as ~ class-name is taken as the “destructor” for objects of a class type. Destructors typically perform cleanup operations at the end of an object’s lifetime. For information on destructors, see Destructors .


Qualified Names

Syntax

qualified-name :

qualified-class-name :: name

If a qualified-class-name is followed by the scope-resolution operator (::) and then the name of a member of either that class or a base of that class, then the scope-resolution operator is considered a qualified-name. The type of a qualified-name is the same as the type of the member, and the result of a qualified-name expression is the member. If the member is an l-value, then the qualified-name is also an l-value. For information about declaring qualified-class-name, see Type Specifiers or Class Names .

The class-name part of a qualified-class-name can be hidden by redeclaration of the same name in the current or enclosing scope; the class-name is still found and used. See Scope for an example of how to use a qualified-class-name to access a hidden class-name.

Note Class constructors and destructors of the form class-name :: class-name and class-name :: ~ class-name, respectively, must refer to the same class-name.

A name with more than one qualification, such as the following, designates a member of a nested class:

class-name :: class-name :: name


Postfix Expressions

Postfix expressions consist of primary expressions or expressions in which postfix operators follow a primary expression. The postfix operators are listed in Table 4.1.

Table 4.1 Postfix Operators

Operator Name | Operator Notation
Subscript operator | [ ]
Function-call operator | ( )
Explicit type conversion operator | type-name( )
Member-selection operator | . or –>
Postfix increment operator | ++
Postfix decrement operator | – –

Syntax

postfix-expression :

primary-expression
postfix-expression [ expression ]
postfix-expression ( expression-listopt )
simple-type-name ( expression-listopt )
postfix-expression . name
postfix-expression –> name
postfix-expression ++
postfix-expression ––

expression-list :

assignment-expression
expression-list , assignment-expression


Subscript Operator

A postfix-expression followed by the subscript operator, [ ], specifies array indexing. One of the expressions must be of pointer or array type — that is, it must have been declared as type* or type[ ]. The other expression must be of an integral type (including enumerated types). In common usage, the expression enclosed in the brackets is the one of integral type, but that is not strictly required. Consider the following example:

MyType m[10];     // Declare an array of a user-defined type.

MyType n1 = m[2]; // Select third element of array.
MyType n2 = 2[m]; // Select third element of array.

In the preceding example, the expression m[2] is identical to 2[m]. Although m is not of an integral type, the effect is the same. The reason that m[2] is equivalent to 2[m] is that the result of a subscript expression e1[ e2 ] is given by:

*( (e2) + (e1) )

The address yielded by the expression is not e2 bytes from the address e1. Rather, the address is scaled to yield the next object in the array e2. For example:

double aDbl[2];

The addresses of aDb[0] and aDb[1] are 8 bytes apart — the size of an object of type double. This scaling according to object type is done automatically by the C++ language and is defined in Additive Operators where addition and subtraction of operands of pointer type is discussed.


Positive and Negative Subscripts

The first element of an array is element 0. The range of a C++ array is from array[0] to array[size – 1]. However, C++ supports positive and negative subscripts. Negative subscripts must fall within array boundaries or results are unpredictable. The following code illustrates this concept:

#include <iostream.h>

void main()
{
    int iNumberArray[1024];
    int *iNumberLine = &iNumberArray[512];

    cout << iNumberArray[-256] << "\n";     // Unpredictable
    cout << iNumberLine[-256] << "\n";      // OK
}

The negative subscript in iNumberArray can produce a run-time error because it yields an address 256 bytes lower in memory than the origin of the array. The object iNumberLine is initialized to the middle of iNumberArray; it is therefore possible to use both positive and negative array indexes on it. Array subscript errors do not generate compile-time errors, but they yield unpredictable results.

The subscript operator is commutative. Therefore, the expressions array[index] and index[array] are guaranteed to be equivalent as long as the subscript operator is not overloaded (see Overloaded Operators). The first form is the most common coding practice, but either works.


Function-Call Operator

A postfix-expression followed by the function-call operator, ( ), specifies a function call. The arguments to the function-call operator are zero or more expressions separated by commas — the actual arguments to the function.

The postfix-expression must be of one of these types:

  • Function returning type T. An example declaration is
    T func( int i )
  • Pointer to a function returning type T. An example declaration is
    T (*func)( int i )
  • Reference to a function returning type T. An example declaration is
    T (&func)(int i)
  • Pointer-to-member function dereference returning type T. Example function calls are
    (pObject->*pmf)();
(Object.*pmf)();


Formal and Actual Arguments

Calling programs pass information to called functions in “actual arguments.” The called functions access the information using corresponding “formal arguments.”

When a function is called, the following tasks are performed:

  • All actual arguments (those supplied by the caller) are evaluated. There is no implied order in which these arguments are evaluated, but all arguments are evaluated and all side effects completed prior to entry to the function.

  • Each formal argument is initialized with its corresponding actual argument in the expression list. (A formal argument is an argument that is declared in the function header and used in the body of a function.) Conversions are done as if by initialization — both standard and user-defined conversions are performed in converting an actual argument to the correct type. The initialization performed is illustrated conceptually by the following code:
    void Func( int i ); // Function prototype
...
Func( 7 );          // Execute function call

    The conceptual initializations prior to the call are:

    int Temp_i = 7;
Func( Temp_i );

    Note that the initialization is performed as if using the equal-sign syntax instead of the parentheses syntax. A copy of i is made prior to passing the value to the function. (For more information, see Initializers and Conversions, Initialization Using Special Member Functions, and Explicit Initialization .

    Therefore, if the function prototype (declaration) calls for an argument of type long, and if the calling program supplies an actual argument of type int, the actual argument is promoted using a standard type conversion to type long (see Chapter 3, Standard Conversions).

    It is an error to supply an actual argument for which there is no standard or user-defined conversion to the type of the formal argument.

    For actual arguments of class type, the formal argument is initialized by calling the class’s constructor. (See Constructors for more about these special class member functions.)

  • The function call is executed.

The following program fragment demonstrates a function call:

void func( long param1, double param2 );

void main()
{
    int i, j;

    // Call func with actual arguments i and j.
    func( i, j );
    ...
}

// Define func with formal parameters param1 and param2.
void func( long param1, double param2 )
{
    ...
}

When func is called from main, the formal parameter param1 is initialized with the value of i (i is converted to type long to correspond to the correct type using a standard conversion), and the formal parameter param2 is initialized with the value of j (j is converted to type double using a standard conversion).


Treatment of Argument Types

Formal arguments declared as const types cannot be changed within the body of a function. Functions can change any argument that is not of type const. However, the change is local to the function and does not affect the actual argument’s value unless the actual argument was a reference to an object not of type const.

The following functions illustrate some of these concepts:

int func1( const int i, int j, char *c )
{
    i = 7;         // Error: i is const.
    j = i;         // OK, but value of j is
                   //  lost at return.
    *c = 'a' + j;  // OK: changes value of c
                   //  in calling function.

    return i;
}

double& func2( double& d, const char *c )
{
    d = 14.387;    // OK: changes value of d
                   //  in calling function.
    *c = 'a';      // Error: c is a pointer to
                   //  a const object.

    return d;
}


Ellipses and Default Arguments

Functions can be declared to accept fewer arguments than specified in the function definition, using one of two methods: ellipsis (...) or default arguments.

Ellipses denote that arguments may be required but that the number and types are not specified in the declaration. This is normally poor C++ programming practice because it defeats one of the benefits of C++: type safety. Different conversions are applied to functions declared with ellipses than to those functions for which the formal and actual argument types are known:

  • If the actual argument is of type float, it is promoted to type double prior to the function call.

  • Any signed or unsigned char, short, enumerated type, or bit field is converted to either a signed or an unsigned int using integral promotion.

  • Any argument of class type is passed by value as a data structure; the copy is created by binary copying instead of by invoking the class’s copy constructor (if one exists).

Ellipses, if used, must be declared last in the argument list. For more information about passing a variable number of arguments, see the discussion of va_arg, va_start, and va_list in the Run-Time Library Reference.

Default arguments enable you to specify the value an argument should assume if none is supplied in the function call. The following code fragment shows how default arguments work. For more information about restrictions on specifying default arguments, see Default Arguments.

#include <iostream.h>

// Declare the function print that prints a string,
// then a terminator.
void print( const char *string,
            const char *terminator = "\n" );

void main()
{
    print( "hello," );
    print( "world!" );

    print( "good morning", ", " );
    print( "sunshine." );
}

// Define print.
void print( char *string, char *terminator )
{
    if( string != NULL )
        cout << string;

    if( terminator != NULL )
        cout << terminator;
}

The preceding program declares a function, print, that takes two arguments. However, the second argument, terminator, has a default value, "\n". In main, the first two calls to print allow the default second argument to supply a new line to terminate the printed string. The third call specifies an explicit value for the second argument. The output from the program is

hello,
world!
good morning, sunshine.


Function-Call Results

A function call evaluates to an r-value unless the function is declared as a reference type. Functions with reference return type evaluate to l-values, and can be used on the left side of an assignment statement as follows:

#include <iostream.h>

class Point
{
public:
    // Define "accessor" functions as
    // reference types.
    unsigned& x() { return _x; }
    unsigned& y() { return _y; }
private:
    unsigned _x;
    unsigned _y;
};

void main()
{
    Point ThePoint;

    ThePoint.x() = 7;           // Use x() as an l-value.
    unsigned y = ThePoint.y();  // Use y() as an r-value.

    // Use x() and y() as r-values.
    cout << "x = " << ThePoint.x() << "\n"
         << "y = " << ThePoint.y() << "\n";
}
000000

The preceding code defines a class called Point, which contains private data objects that represent x and y coordinates. These data objects must be modified and their values retrieved. This program is only one of several designs for such a class; use of the GetX and SetX or GetY and SetY functions is another possible design.

Functions that return class types, pointers to class types, or references to class types can be used as the left operand to member-selection operators. Therefore, the following code is legal:

class A
{
public:
    int SetA( int i ) { return (I = i); }
    int GetA()    { return I; }

private:
    int I;
};

// Declare three functions:
//  func1, which returns type A
//  func2, which returns a pointer to type A
//  func3, which returns a reference to type A
A func1();
A* func2();
A& func3();

int iResult = func1().GetA();
func2()->SetA( 3 );
func3().SetA( 7 );

Functions can be called recursively. For more information about function declarations, see Function Specifiers and Member Functions. Related material is in Program and Linkage.


Member-Selection Operator

A postfix-expression followed by the member-selection operator (.) and a name is another example of a postfix-expression. The first operand of the member-selection operator must have class or class reference type, and the second operand must identify a member of that class.

The result of the expression is the value of the member, and it is an l-value if the named member is an l-value.

A postfix-expression followed by the member-selection operator (–>) and a name is a postfix-expression. The first operand of the member-selection operator must have type pointer to a class object (an object declared as class, struct, or union type), and the second operand must identify a member of that class.

The result of the expression is the value of the member, and it is an l-value if the named member is an l-value. The –> operator dereferences the pointer. Therefore, the expressions e–>member and (*e).member (where e represents an expression) yield identical results (except when the operators –> or * are overloaded).

When a value is stored through one member of a union but retrieved through another member, no conversion is performed. The following program stores data into the object U as int but retrieves the data as two separate bytes of type char:

#include <iostream.h>

void main()
{
    struct ch
    {
        char b1;
        char b2;
    };
    union u
    {
        struct ch uch;
        short  i;
    };

    u U;

    U.i = 0x6361;  // Bit pattern for "ac"
    cout << U.uch.b1 << U.uch.b2 << "\n";
}


C++ Postfix Increment and Decrement Operators

C++ provides prefix and postfix increment and decrement operators; this section describes only the postfix increment and decrement operators. (For more information, see Increment and Decrement Operators.) The difference between the two is that in the postfix notation, the operator appears after postfix-expression, whereas in the prefix notation, the operator appears before expression. The following example shows a postfix-increment operator:

i++

The effect of applying the postfix increment, or “postincrement,” operator (++) is that the operand’s value is increased by one unit of the appropriate type. Similarly, the effect of applying the postfix decrement, or “postdecrement,” operator (––) is that the operand’s value is decreased by one unit of the appropriate type.

For example, applying the postincrement operator to a pointer to an array of objects of type long actually adds four to the internal representation of the pointer. This behavior causes the pointer, which previously referred to the nth element of the array, to refer to the (n+1)th element.

The operands to postincrement and postdecrement operators must be modifiable (not const) l-values of arithmetic or pointer type. The result of the postincrement or postdecrement expression is the value of the postfix-expression prior to application of the increment operator. The type of the result is the same as that of the postfix-expression, but it is no longer an l-value.

The following code illustrates the postfix increment operator.

if( var++ > 0 )
    *p++ = *q++;

In this example, the variable var is compared to 0, then incremented. If var was positive before being incremented, the next statement is executed. First, the value of the object pointed to by q is assigned to the object pointed to by p. Then, q and p are incremented.

Postincrement and postdecrement, when used on enumerated types, yield integral values. Therefore, the following code is illegal:

enum Days {
    Sunday = 1,
    Monday,
    Tuesday,
    Wednesday,
    Thursday,
    Friday,
    Saturday
};

void main()
{
  Days Today = Tuesday;
  Days SaveToday;

  SaveToday = Today++;  // error
}

The intent of this code is to save today’s day and then move to tomorrow. However, the result is that the expression Today++ yields an int — an error when assigned to an object of the enumerated type Days.


Expressions with Unary Operators

Unary operators act on only one operand in an expression. The unary operators are:

  • Indirection operator (*)

  • Address-of operator (&)

  • Unary plus operator (+)

  • Unary negation operator (–)

  • Logical NOT operator (!)

  • One’s complement operator (~)

  • Prefix increment operator (++)

  • Prefix decrement operator (––)

  • sizeof operator

  • new operator

  • delete operator

These operators have right-to-left associativity.

Syntax

unary-expression :

postfix-expression
++unary-expression
––unary-expression
unary-operator cast-expression
sizeof .unary-expression
sizeof ( type-name )
allocation-expression
deallocation-expression

unary-operator : one of

* & + – ! ~


Indirection Operator (*)

The unary indirection operator (*) “dereferences” a pointer; that is, it converts a pointer value to an l-value. The operand of the indirection operator must be a pointer to a type. The result of the indirection expression is the type from which the pointer type is derived. The use of the * operator in this context is different from its meaning as a binary operator, which is multiplication.

If the operand points to a function, the result is a function designator. If it points to a storage location, the result is an l-value designating the storage location.

If the pointer value is invalid, the result is undefined. The following list includes some of the most common conditions that invalidate a pointer value.

  • The pointer is a null pointer.

  • The pointer specifies the address of a local item that is not visible at the time of the reference.

  • The pointer specifies an address that is inappropriately aligned for the type of the object pointed to.

  • The pointer specifies an address not used by the executing program.


Address-Of Operator (&)

The unary address-of operator (&) takes the address of its operand. The address-of operator can be applied only to the following:

  • Functions (although its use for taking the address of a function is unnecessary)

  • L-values

  • Qualified names

In the first two cases listed above, the result of the expression is a pointer type (an r-value) derived from the type of the operand. For example, if the operand is of type char, the result of the expression is of type pointer to char. The address-of operator, applied to const or volatile objects, evaluates to const type * or volatile type *, where type is the type of the original object.

The result produced by the third case, applying the address-of operator to a qualified-name, depends on whether the qualified-name specifies a static member. If so, the result is a pointer to the type specified in the declaration of the member. If the member is not static, the result is a pointer to the member name of the class indicated by qualified-class-name. (See Primary Expressions for more about qualified-class-name.) The following code fragment shows how the result differs, depending on whether the member is static:

class PTM
{
public:
           int   iValue;
    static float fValue;
};

int   PTM::*piValue = &PTM::iValue;  // OK: non-static
float PTM::*pfValue = &PTM::fValue;  // Error: static
float *spfValue     = &PTM::fValue;  // OK

In this example, the expression &PTM::fValue yields type float * instead of type float PTM::* because fValue is a static member.

The address of an overloaded function can be taken only when it is clear which version of the function is being referenced. See Address of Overloaded Functions for information about how to obtain the address of a particular overloaded function.

Applying the address-of operator to a reference type gives the same result as applying the operator to the object to which the reference is bound. The following program demonstrates this concept:

#include <iostream.h>

void main()
{
    double d;        // Define an object of type double.
    double& rd = d;  // Define a reference to the object.

    // Compare the address of the object to the address
    //  of the reference to the object.
    if( &d == &rd )
        cout << "&d equals &rd" << "\n";
    else
        cout << "&d is not equal to &rd" << "\n";
}

The output from the program is always &d equals &rd.


Unary Plus Operator (+)

The result of the unary plus operator (+) is the value of its operand. The operand to the unary plus operator must be of an arithmetic type.

Integral promotion is performed on integral operands. The resultant type is the type to which the operand is promoted. Thus, the expression +ch, where ch is of type char, results in type int; the value is unmodified. See Integral Promotions for more information about how the promotion is done.


Unary Negation Operator (-)

The unary negation operator (–) produces the negative of its operand. The operand to the unary negation operator must be an arithmetic type.

Integral promotion is performed on integral operands, and the resultant type is the type to which the operand is promoted. See Integral Promotions for more information on how the promotion is done.

Microsoft Specific

Unary negation of unsigned quantities is performed by subtracting the value of the operand from 2n, where n is the number of bits in an object of the given unsigned type. (Microsoft C++ runs on processors that utilize two’s-complement arithmetic. On other processors, the algorithm for negation can differ.)

END Microsoft Specific


Logical NOT Operator (!)

The result of the logical NOT operator (!) is 0 if its operand evaluates to a nonzero value; the result is 1 only if the operand is equal to 0. The operand must be of arithmetic or pointer type. The result is of type int.

For an expression e, the unary expression !e is equivalent to the expression
(e == 0), except where overloaded operators are involved.

The following example illustrates the logical NOT operator (!):

if( !(x < y) )

If x is greater than or equal to y, the result of the expression is 1 (true). If x is less than y, the result is 0 (false).

Unary arithmetic operations on pointers are illegal.


One's Complement Operator (~)

One’s Complement Operator (~)

The one’s complement operator (~), sometimes called the “bitwise complement” operator, yields a bitwise one’s complement of its operand. That is, every bit that is set in the operand is 0 in the result. Conversely, every bit that is 0 in the operand is set in the result. The operand to the one’s complement operator must be an integral type.

unsigned short y = 0xAAAA;
    y = ~y;

In this example, the new value assigned to y is the one’s complement of the unsigned value 0xAAAA, or 0x5555.

Integral promotion is performed on integral operands, and the resultant type is the type to which the operand is promoted. See Integral Promotions for more information on how the promotion is done.


Increment and Decrement Operators (++, --)

The prefix increment operator (++), also called the “preincrement” operator, adds one to its operand; this incremented value is the result of the expression. The operand must be an l-value not of type const. The result is an l-value of the same type as the operand.

The prefix decrement operator (––), also called the “predecrement” operator, is analogous to the preincrement operator, except that the operand is decremented by one and the result is this decremented value.

Both the prefix and postfix increment and decrement operators affect their operands. The key difference between them is when the increment or decrement takes place in the evaluation of an expression. (For more information, see Postfix Increment and Decrement Operators.) In the prefix form, the increment or decrement takes place before the value is used in expression evaluation, so the value of the expression is different from the value of the operand. In the postfix form, the increment or decrement takes place after the value is used in expression evaluation, so the value of the expression is the same as the value of the operand.

An operand of integral or floating type is incremented or decremented by the integer value 1. The type of the result is the same as the operand type. An operand of pointer type is incremented or decremented by the size of the object it addresses. An incremented pointer points to the next object; a decremented pointer points to the previous object.

This example illustrates the unary decrement operator:

if( line[--i] != '\n' )
    return;

In this example, the variable i is decremented before it is used as a subscript to line.

Because increment and decrement operators have side effects, using expressions with increment or decrement operators in a macro can have undesirable results (see Macros in the Preprocessor Reference for more information about macros). Consider this example:

#define max(a,b) ((a)<(b))?(b):(a)

...

int i, j, k;

k = max( ++i, j );

The macro expands to:

k = ((++i)<(j))?(j):(++i);

If i is greater than or equal to j, it will be incremented twice.

Note C++ inline functions are preferable to macros in many cases because they eliminate side effects such as those described here, and allow the language to perform more complete type checking.


sizeof Operator

The sizeof operator yields the size of its operand with respect to the size of type char. The result of the sizeof operator is of type size_t, an integral type defined in the include file STDDEF.H. The operand to sizeof can be one of the following:

  • A type name. To use sizeof with a type name, the name must be enclosed in parentheses.

  • An expression. When used with an expression, sizeof can be specified with or without the parentheses. The expression is not evaluated.

When the sizeof operator is applied to an object of type char, it yields 1. When the sizeof operator is applied to an array, it yields the total number of bytes in that array. For example:

#include <iostream.h>

void main()
{
    char szHello[] = "Hello, world!";

    cout << "The size of the type of " << szHello << " is: "
         << sizeof( char ) << "\n";
    cout << "The length of " << szHello << " is: "
         << sizeof szHello << "\n";
}

The program output is:

The size of the type of Hello, world! is: 1
The length of Hello, world! is: 14

When the sizeof operator is applied to a class, struct, or union type, the result is the number of bytes in an object of that class, struct, or union type, plus any padding added to align members on word boundaries. (The /Zp [pack structure members] compiler option and the pack pragma affect alignment boundaries for members.) The sizeof operator never yields 0, even for an empty class.

The sizeof operator cannot be used with the following operands:

  • Functions. (However, sizeof can be applied to pointers to functions.)

  • Bit fields.

  • Undefined classes.

  • The type void.

  • Incomplete types.

  • Parenthesized names of incomplete types.

When the sizeof operator is applied to a reference, the result is the same as if sizeof had been applied to the object itself.

The sizeof operator is often used to calculate the number of elements in an array using an expression of the form:

sizeof array / sizeof array[0]


new Operator

The new operator attempts to dynamically allocate (at run time) one or more objects of type-name. The new operator cannot be used to allocate a function; however, it can be used to allocate a pointer to a function.

Syntax

allocation-expression :

::opt new placementopt new-type-name new-initializeropt
::opt new placementopt ( type-name ) new-initializeropt

placement :

( expression-list )

new-type-name :

type-specifier-list new-declaratoropt

The new operator is used to allocate objects and arrays of objects. The new operator allocates from a program memory area called the “free store.” In C, the free store is often referred to as the “heap.”

When new is used to allocate a single object, it yields a pointer to that object; the resultant type is new-type-name * or type-name *. When new is used to allocate a singly dimensioned array of objects, it yields a pointer to the first element of the array, and the resultant type is new-type-name * or type-name *. When new is used to allocate a multidimensional array of objects, it yields a pointer to the first element of the array, and the resultant type preserves the size of all but the leftmost array dimension. For example:

new float[10][25][10]

yields type float (*)[25][10]. Therefore, the following code will not work because it attempts to assign a pointer to an array of float with the dimensions [25][10] to a pointer to type float:

float *fp;
fp = new float[10][25][10];

The correct expression is:

float (*cp)[25][10];
cp = new float[10][25][10];

The definition of cp allocates a pointer to an array of type float with dimensions [25][10] — it does not allocate an array of pointers.

All but the leftmost array dimensions must be constant expressions that evaluate to positive values; the leftmost array dimension can be any expression that evaluates to a positive value. When allocating an array using the new operator, the first dimension can be zero — the new operator returns a unique pointer.

The type-specifier-list cannot contain const, volatile, class declarations, or enumeration declarations. Therefore, the following expression is illegal:

volatile char *vch = new volatile char[20];

The new operator does not allocate reference types because they are not objects.

If there is insufficient memory for the allocation request, by default operator new returns NULL. You can change this default behavior by writing a custom exception-handling routine and calling the _set_new_handler run-time library function with your function name as its argument. For more details on this recovery scheme, see The operator new Function.


Lifetime of Objects Allocated with new

Objects allocated with the new operator are not destroyed when the scope in which they are defined is exited. Because the new operator returns a pointer to the objects it allocates, the program must define a pointer with suitable scope to access those objects. For example:

void main()
{
    // Use new operator to allocate an array of 20 characters.
    char *AnArray = new char[20];

    for( int i = 0; i < 20; ++i )
    {
        // On the first iteration of the loop, allocate
        //  another array of 20 characters.
        if( i == 0 )
        {
            char *AnotherArray = new char[20];
        }
        ...
    }

    delete AnotherArray; // Error: pointer out of scope.
    delete AnArray;      // OK: pointer still in scope.
}

Once the pointer AnotherArray goes out of scope in the example, the object can no longer be deleted.


Initializing Objects Allocated with new

An optional new-initializer field is included in the syntax for the new operator. This allows new objects to be initialized with user-defined constructors. For more information about how initialization is done, see Initializers in Chapter 7.

The following example illustrates how to use an initialization expression with the new operator:

#include <iostream.h>

class Acct
{
public:
    // Define default constructor and a constructor that accepts
    //  an initial balance.
    Acct() { balance = 0.0; }
    Acct( double init_balance ) { balance = init_balance; }
private:
    double balance;
};

void main()
{
    Acct *CheckingAcct = new Acct;
    Acct *SavingsAcct = new Acct ( 34.98 );
    double *HowMuch = new double ( 43.0 );
    ...
}

In this example, the object CheckingAcct is allocated using the new operator, but no default initialization is specified. Therefore, the default constructor for the class, Acct(), is called. Then the object SavingsAcct is allocated the same way, except that it is explicitly initialized to 34.98. Because 34.98 is of type double, the constructor that takes an argument of that type is called to handle the initialization. Finally, the nonclass type HowMuch is initialized to 43.0.

If an object is of a class type and that class has constructors (as in the preceding example), the object can be initialized by the new operator only if one of these conditions is met:

  • The arguments provided in the initializer agree with those of a constructor.

  • The class has a default constructor (a constructor that can be called with no arguments).

Access control and ambiguity control are performed on operator new and on the constructors according to the rules set forth in Ambiguity in Chapter 9 and Initialization Using Special Member Functions in Chapter 11.

No explicit per-element initialization can be done when allocating arrays using the new operator; only the default constructor, if present, is called. See Default Arguments in Chapter 7 for more information.

If the memory allocation fails (operator new returns a value of 0), no initialization is performed. This protects against attempts to initialize data that does not exist.

As with function calls, the order in which initialized expressions are evaluated is not defined. Furthermore, you should not rely on these expressions being completely evaluated before the memory allocation is performed. If the memory allocation fails and the new operator returns zero, some expressions in the initializer may not be completely evaluated.


How new Works

The allocation-expression — the expression containing the new operator — does three things:

  • Locates and reserves storage for the object or objects to be allocated. When this stage is complete, the correct amount of storage is allocated, but it is not yet an object.

  • Initializes the object(s). Once initialization is complete, enough information is present for the allocated storage to be an object.

  • Returns a pointer to the object(s) of a pointer type derived from new-type-name or type-name. The program uses this pointer to access the newly allocated object.

The new operator invokes the function operator new. For arrays of any type, and for objects that are not of class, struct, or union types, a global function, ::operator new, is called to allocate storage. Class-type objects can define their own operator new static member function on a per-class basis.

When the compiler encounters the new operator to allocate an object of type type, it issues a call to type::operator new( sizeof( type ) ) or, if no user-defined operator new is defined, ::operator new( sizeof( type ) ). Therefore, the new operator can allocate the correct amount of memory for the object.

Note The argument to operator new is of type size_t. This type is defined in DIRECT.H, MALLOC.H, MEMORY.H, SEARCH.H, STDDEF.H, STDIO.H, STDLIB.H, STRING.H, and TIME.H.

An option in the syntax allows specification of placement (see Syntax for new Operator). The placement parameters can be used only for user-defined implementations of operator new; it allows extra information to be passed to operator new. An expression with a placement field such as

T *TObject = new ( 0x0040 ) T;

is translated to

T *TObject = T::operator new( sizeof( T ), 0x0040 );

The original intention of the placement field was to allow hardware-dependent objects to be allocated at user-specified addresses.

Note Although the preceding example shows only one argument in the placement field, there is no restriction on how many extra arguments can be passed to operator new this way.

Even when operator new has been defined for a class type, the global operator can be used by using the form of this example:

T *TObject =::new TObject;

The scope-resolution operator (::) forces use of the global new operator.


delete Operator

The delete operator deallocates an object created with the new operator. The delete operator has a result of type void and therefore does not return a value. The operand to delete must be a pointer returned by the new operator.

Using delete on a pointer to an object not allocated with new gives unpredictable results. You can, however, use delete on a pointer with the value 0. This provision means that, because new always returns 0 on failure, deleting the result of a failed new operation is harmless.

Syntax

deallocation-expression :

::opt delete cast-expression
::opt delete [ ] cast-expression

Using the delete operator on an object deallocates its memory. A program that dereferences a pointer after the object is deleted can have unpredictable results or crash.

If the operand to the delete operator is a modifiable l-value, its value is undefined after the object is deleted.

Pointers to const objects cannot be deallocated with the delete operator.


How delete Works

The delete operator invokes the function operator delete. For objects of class types (class, struct, and union), the delete operator invokes the destructor for an object prior to deallocating memory (if the pointer is not null). For objects not of class type, the global delete operator is invoked. For objects of class type, the delete operator can be defined on a per-class basis; if there is no such definition for a given class, the global operator is invoked.


Using delete

There are two syntactic variants for the delete operator: one for single objects and the other for arrays of objects. The following code fragment shows how these differ:

void main()
{
    // Allocate a user-defined object, UDObject, and an object
    //  of type double on the free store using the
    //  new operator.
    UDType *UDObject = new UDType;
    double *dObject = new double;
    ...
    // Delete the two objects.
    delete UDObject;
    delete dObject;
    ...
    // Allocate an array of user-defined objects on the
    // free store using the new operator.
    UDType (*UDArr)[7] = new UDType[5][7];
    ...
    // Use the array syntax to delete the array of objects.
    delete [] UDArr;
}

These two cases produce undefined results: using the array form of delete (delete [ ]) on an object and using the nonarray form of delete on an array.


Expressions with Binary Operators

Binary operators act on two operands in an expression. The binary operators are:

  • Multiplicative operators
    • Multiplication (*)

    • Division (/)

    • Modulus (%)
  • Additive operators
    • Addition (+)

    • Subtraction (–)
  • Shift operators
    • Right shift (>>)

    • Left shift (<<)
  • Relational and equality operators
    • Less than (<)

    • Greater than (>)

    • Less than or equal to (<=)

    • Greater than or equal to (>=)

    • Equal to (==)

    • Not equal to (!=)
  • Bitwise operators
    • Bitwise AND (&)

    • Bitwise exclusive OR (^)

    • Bitwise inclusive OR (|)

    • Logical AND (&&)

    • Logical OR (||)


C++ Multiplicative Operators

The multiplicative operators are:

  • Multiplication (*)

  • Division (/)

  • Modulus or “remainder from division” (%)

These binary operators have left-to-right associativity.

Syntax

multiplicative-expression :

pm-expression
multiplicative-expression * pm-expression
multiplicative-expression / pm-expression
multiplicative-expression % pm-expression

The multiplicative operators take operands of arithmetic types. The modulus operator (%) has a stricter requirement in that its operands must be of integral type. (To get the remainder of a floating-point division, use the run-time function, fmod.) The conversions covered in Arithmetic Conversions in Chapter 3 are applied to the operands, and the result is of the converted type.

The multiplication operator yields the result of multiplying the first operand by the second.

The division operator yields the result of dividing the first operand by the second.

The modulus operator yields the remainder given by the following expression, where e1 is the first operand and e2 is the second: e1 – (e1 / e2) * e2, where both operands are of integral types.

Division by 0 in either a division or a modulus expression is undefined and causes a run-time error. Therefore, the following expressions generate undefined, erroneous results:

i % 0
f / 0.0

If both operands to a multiplication, division, or modulus expression have the same sign, the result is positive. Otherwise, the result is negative. The result of a modulus operation’s sign is implementation-defined.

Microsoft Specific

In Microsoft C++, the result of a modulus expression is always the same as the sign of the first operand.

END Microsoft Specific

If the computed division of two integers is inexact and only one operand is negative, the result is the largest integer (in magnitude, disregarding the sign) that is less than the exact value the division operation would yield. For example, the computed value of –11 / 3 is –3.666666666. The result of that integral division is –3.

The relationship between the multiplicative operators is given by the identity
(e1 / e2) * e2 + e1 % e2 == e1.


C++ Additive Operators

The additive operators are:

  • Addition (+)

  • Subtraction (–)

These binary operators have left-to-right associativity.

Syntax

additive-expression :

multiplicative-expression
additive-expression + multiplicative-expression
additive-expression – multiplicative-expression

The additive operators take operands of arithmetic or pointer types. The result of the addition (+) operator is the sum of the operands. The result of the subtraction (–) operator is the difference between the operands. If one or both of the operands are pointers, they must be pointers to objects, not to functions.

Additive operators take operands of arithmetic, integral, and scalar types. These are defined in Table 4.2.

Table 4.2 Types Used with Additive Operators

Type | Meaning
arithmetic | Integral and floating types are collectively called “arithmetic” types.
integral | Types char and int of all sizes (long, short) and enumerations are “integral” types.
scalar | Scalar operands are operands of either arithmetic or pointer type.

The legal combinations for these operators are:

arithmetic + arithmetic
scalar + integral
integral + scalar
arithmetic – arithmetic
scalar – scalar

Note that addition and subtraction are not equivalent operations.

If both operands are of arithmetic type, the conversions covered in Arithmetic Conversions in Chapter 3 are applied to the operands, and the result is of the converted type.


Addition of Pointer Types

If one of the operands in an addition operation is a pointer to an array of objects, the other must be of integral type. The result is a pointer that is of the same type as the original pointer and that points to another array element. The following code fragment illustrates this concept:

short IntArray[10]; // Objects of type short occupy 2 bytes
short *pIntArray = IntArray;

for( int i = 0; i < 10; ++i )
{
    *pIntArray = i;
    cout << *pIntArray << "\n";
    pIntArray = pIntArray + 1;
}

Although the integral value 1 is added to pIntArray, it does not mean “add 1 to the address”; rather it means “adjust the pointer to point to the next object in the array” that happens to be 2 bytes (or sizeof( int )) away.

Note Code of the form pIntArray = pIntArray + 1 is rarely found in C++ programs; to perform an increment, these forms are preferable: pIntArray++ or pIntArray += 1.


Subtraction of Pointer Types

If both operands are pointers, the result of subtraction is the difference (in array elements) between the operands. The subtraction expression yields a signed integral result of type ptrdiff_t (defined in the standard include file STDDEF.H).

One of the operands can be of integral type, as long as it is the second operand. The result of the subtraction is of the same type as the original pointer. The value of the subtraction is a pointer to the (n – i)th array element, where n is the element pointed to by the original pointer and i is the integral value of the second operand.


Shift Operators

The bitwise shift operators are:

  • Right shift (>>)

  • Left shift (<<)

These binary operators have left-to-right associativity.

Syntax

shift-expression :

additive-expression
shift-expression << additive-expression
shift-expression >> additive-expression

Both operands of the shift operators must be of integral types. Integral promotions are performed according to the rules described in Integral Promotions in Chapter 3. The type of the result is the same as the type of the left operand. The value of a right-shift expression e1 >> e2 is e1 / 2e2, and the value of a left-shift expression e1 << e2 is e1 * 2e2.

The results are undefined if the right operand of a shift expression is negative or if the right operand is greater than or equal to the number of bits in the (promoted) left operand.

The left-shift operator causes the bit pattern in the first operand to be shifted left the number of bits specified by the second operand. Bits vacated by the shift operation are zero-filled. This is a logical shift, as opposed to a shift-and-rotate operation.

The right-shift operator causes the bit pattern in the first operand to be shifted right the number of bits specified by the second operand. Bits vacated by the shift operation are zero-filled for unsigned quantities. For signed quantities, the sign bit is propagated into the vacated bit positions. The shift is a logical shift if the left operand is an unsigned quantity; otherwise, it is an arithmetic shift.

Microsoft Specific

The result of a right shift of a signed negative quantity is implementation dependent. Although Microsoft C++ propagates the most-significant bit to fill vacated bit positions, there is no guarantee that other implementations will do likewise.

END Microsoft Specific


C++ Relational and Equality Operators

The relational and equality operators determine equality, inequality, or relative values of their operands. The relational operators are shown in Table 4.3.

Table 4.3 Relational and Equality Operators

Operator | Meaning
== | Equal to
!= | Not equal to
< | Less than
> | Greater than
<= | Less than or equal to
>= | Greater than or equal to


Relational Operators

The binary relational operators determine the following relationships:

  • Less than

  • Greater than

  • Less than or equal to

  • Greater than or equal to

Syntax

relational-expression :

shift-expression
relational-expression < shift-expression
relational-expression > shift-expression
relational-expression <= shift-expression
relational-expression >= shift-expression

The relational operators have left-to-right associativity. Both operands of relational operators must be of arithmetic or pointer type. They yield values of type int. The value returned is 0 if the relationship in the expression is false; otherwise, it is 1. Consider the following code, which demonstrates several relational expressions:

#include <iostream.h>

void main()
{
    cout << "The true expression 3 > 2 yields: "
         << (3 > 2) << "\n";
    cout << "The false expression 20 < 10 yields: "
         << (20 < 10) << "\n";
    cout << "The expression 10 < 20 < 5 yields: "
         << (10 < 20 < 5) << "\n";
}

The output from this program is:

The true expression 3 > 2 yields 1
The false expression 20 < 10 yields 0
The expression 10 < 20 < 5 yields 1

The expressions in the preceding example must be enclosed in parentheses because the insertion operator (<<) has higher precedence than the relational operators. Therefore, the first expression without the parentheses would be evaluated as:

(cout << "The true expression 3 > 2 yields: " << 3) < (2 << "\n");

Note that the third expression evaluates to 1 — because of the left-to-right associativity of relational operators, the explicit grouping of the expression 10 < 20 < 5 is:

(10 < 20) < 5

Therefore, the test performed is:

1 < 5

and the result is 1 (or true).

The usual arithmetic conversions covered in Arithmetic Conversions in Chapter 3 are applied to operands of arithmetic types.


Comparing Pointers Using Relational Operators

When two pointers to objects of the same type are compared, the result is determined by the location of the objects pointed to in the program’s address space. Pointers can also be compared to a constant expression that evaluates to 0 or to a pointer of type void *. If a pointer comparison is made against a pointer of type void *, the other pointer is implicitly converted to type void *. Then the comparison is made.

Two pointers of different types cannot be compared unless:

  • One type is a class type derived from the other type.

  • At least one of the pointers is explicitly converted (cast) to type void *. (The other pointer is implicitly converted to type void * for the conversion.)

Two pointers of the same type that point to the same object are guaranteed to compare equal. If two pointers to nonstatic members of an object are compared, the following rules apply:

  • If the class type is not a union, and if the two members are not separated by an access-specifier, such as public, protected, or private, the pointer to the member declared last will compare greater than the pointer to the member declared earlier. (For information on access-specifier, see the Syntax section in Access Specifiers in Chapter 10.)

  • If the two members are separated by an access-specifier, the results are undefined.

  • If the class type is a union, pointers to different data members in that union compare equal.

If two pointers point to elements of the same array or to the element one beyond the end of the array, the pointer to the object with the higher subscript compares higher. Comparison of pointers is guaranteed valid only when the pointers refer to objects in the same array or to the location one past the end of the array.


Equality Operators

The binary equality operators compare their operands for strict equality or inequality.

Syntax

equality-expression :

relational-expression
equality-expression == relational-expression
equality-expression != relational-expression

The equality operators, equal to (==) and not equal to (!=), have lower precedence than the relational operators, but they behave similarly.

The equal-to operator (==) returns true if both operands have the same value; otherwise, it returns false. The not-equal-to operator (!=) returns true if the operands do not have the same value; otherwise, it returns false.

Equality operators can compare pointers to members of the same type. In such a comparison, pointer-to-member conversions, as discussed in Pointer-to-Member Conversions in Chapter 3 are performed. Pointers to members can also be compared to a constant expression that evaluates to 0.


C++ Bitwise Operators

The bitwise operators are:

  • Bitwise AND (&)

  • Bitwise exclusive OR (^)

  • Bitwise inclusive OR (|)

These operators return bitwise combinations of their operands.


Bitwise AND Operator

The bitwise AND operator (&) returns the bitwise AND of the two operands. All bits that are on (1) in both the left and right operand are on in the result; bits that are off (0) in either the left or the right operand are off in the result.

Syntax

and-expression :

relational-expression
and-expression & equality-expression

Both operands to the bitwise AND operator must be of integral types. The usual arithmetic conversions covered in Arithmetic Conversions in Chapter 3, are applied to the operands.


Bitwise Exclusive OR Operator

The bitwise exclusive OR operator (^) returns the bitwise exclusive OR of the two operands. All bits that are on (1) in either the left or right operand, but not both, are on in the result. Bits that are the same (either on or off) in both operands are off in the result.

Syntax

exclusive-or-expression :

and-expression
exclusive-or-expression ^ and-expression

Both operands to the bitwise exclusive OR operator must be of integral types. The usual arithmetic conversions covered in Arithmetic Conversions in Chapter 3 are applied to the operands.


Bitwise Inclusive OR Operator

The bitwise inclusive OR operator (|) returns the bitwise inclusive OR of the two operands. All bits that are on (1) in either the left or right operand are on in the result. Bits that are off (0) in both operands are off in the result.

Syntax

inclusive-or-expression :

exclusive-or-expression
inclusive-or-expression | exclusive-or-expression

Both operands to the bitwise inclusive OR operator must be of integral types. The usual arithmetic conversions covered in Arithmetic Conversions in Chapter 3 are applied to the operands.


C++ Logical Operators

The logical operators, logical AND (&&) and logical OR (||), are used to combine multiple conditions formed using relational or equality expressions.


Logical AND Operator

The logical AND operator (&&) returns the integral value 1 if both operands are nonzero; otherwise, it returns 0. Logical AND has left-to-right associativity.

Syntax

logical-and-expression :

inclusive-or-expression
logical-and-expression && inclusive-or-expression

The operands to the logical AND operator need not be of the same type, but they must be of integral or pointer type. The operands are commonly relational or equality expressions.

The first operand is completely evaluated and all side effects are completed before continuing evaluation of the logical AND expression.

The second operand is evaluated only if the first operand evaluates to true (nonzero). This evaluation eliminates needless evaluation of the second operand when the logical AND expression is false. You can use this short-circuit evaluation to prevent null-pointer dereferencing, as shown in the following example:

char *pch = 0;
...
(pch) && (*pch = 'a');

If pch is null (0), the right side of the expression is never evaluated. Therefore, the assignment through a null pointer is impossible.


Logical OR Operator

The logical OR operator (||) returns the integral value 1 if either operand is nonzero; otherwise, it returns 0. Logical OR has left-to-right associativity.

Syntax

logical-or-expression :

logical-and-expression
logical-or-expression || logical-and-expression

The operands to the logical OR operator need not be of the same type, but they must be of integral or pointer type. The operands are commonly relational or equality expressions.

The first operand is completely evaluated and all side effects are completed before continuing evaluation of the logical OR expression.

The second operand is evaluated only if the first operand evaluates to false (0). This eliminates needless evaluation of the second operand when the logical OR expression is true.

printf( "%d" , (x == w || x == y || x == z) );

In this example, if x is equal to either w, y, or z, the second argument to the printf function evaluates to true and the value 1 is printed. Otherwise, it evaluates to false and the value 0 is printed. As soon as one of the conditions evaluates to true, evaluation ceases.


C++ Assignment Operators

Assignment operators store a value in the object designated by the left operand. There are two kinds of assignment operations: “simple assignment,” in which the value of the second operand is stored in the object specified by the first operand, and “compound assignment,” in which an arithmetic, shift, or bitwise operation is performed prior to storing the result. All assignment operators in Table 4.4 except the = operator are compound assignment operators.

Table 4.4 Assignment Operators

Operator | Meaning
= | Store the value of the second operand in the object specified by the first operand (“simple assignment”).
*= | Multiply the value of the first operand by the value of the second operand; store the result in the object specified by the first operand.
/= | Divide the value of the first operand by the value of the second operand; store the result in the object specified by the first operand.
%= | Take modulus of the first operand specified by the value of the second operand; store the result in the object specified by the first operand.
+= | Add the value of the second operand to the value of the first operand; store the result in the object specified by the first operand.
–= | Subtract the value of the second operand from the value of the first operand; store the result in the object specified by the first operand.
<<= | Shift the value of the first operand left the number of bits specified by the value of the second operand; store the result in the object specified by the first operand.
>>= | Shift the value of the first operand right the number of bits specified by the value of the second operand; store the result in the object specified by the first operand.
&= | Obtain the bitwise AND of the first and second operands; store the result in the object specified by the first operand.
^= | Obtain the bitwise exclusive OR of the first and second operands; store the result in the object specified by the first operand.
|= | Obtain the bitwise inclusive OR of the first and second operands; store the result in the object specified by the first operand.

Syntax

assignment-expression :

conditional-expression
unary-expression assignment-operator assignment-expression

assignment-operator : one of

= *= /= %= += –= <<= >>= &= ^= |=


Result of Assignment Operators

The assignment operators return the value of the object specified by the left operand after the assignment. The resultant type is the type of the left operand. The result of an assignment expression is always an l-value. These operators have right-to-left associativity. The left operand must be a modifiable l-value.

Note In ANSI C, the result of an assignment expression is not an l-value. Therefore, the legal C++ expression (a += b) += c is illegal in C.


Simple Assignment

The simple assignment operator (=) causes the value of the second operand to be stored in the object specified by the first operand. If both objects are of arithmetic types, the right operand is converted to the type of the left, prior to storing the value.

Objects of const and volatile types can be assigned to l-values of types that are just volatile or that are neither const nor volatile.

Assignment to objects of class type (struct, union, and class types) is performed by a function named operator=. The default behavior of this operator function is to perform a bitwise copy; however, this behavior can be modified using overloaded operators. (See Overloaded Operators in Chapter 12 for more information.)

An object of any unambiguously derived class from a given base class can be assigned to an object of the base class. The reverse is not true because there is an implicit conversion from derived class to base class but not from base class to derived class. For example:

#include <iostream.h>

class ABase
{
public:
    ABase() { cout << "constructing ABase\n"; }
};

class ADerived : public ABase
{
public:
    ADerived() { cout << "constructing ADerived\n"; }
};

void main()
{
    ABase aBase;
    ADerived aDerived;

    aBase = aDerived; // OK
    aDerived = aBase; // Error
}

Assignments to reference types behave as if the assignment were being made to the object to which the reference points.

For class-type objects, assignment is different from initialization. To illustrate how different assignment and initialization can be, consider the code

UserType1 A;
UserType2 B = A;

The preceding code shows an initializer; it calls the constructor for UserType1 that takes an argument of type UserType1. Given the code

UserType1 A;
UserType2 B;

B = A;

the assignment statement

B = A;

can have one of the following effects:

  • Call the function operator= for UserType2, provided operator= is provided with a UserType1 argument.

  • Call the explicit conversion function UserType1::operator UserType2, if such a function exists.

  • Call a constructor UserType2::UserType2, provided such a constructor exists, that takes a UserType1 argument and copies the result.


C++ Compound Assignment

The compound assignment operators, shown in Table 4.4, are specified in the form e1 op= e2, where e1 is a modifiable l-value not of const type and e2 is one of the following:

  • An arithmetic type

  • A pointer, if op is + or –

The e1 op= e2 form behaves as e1 = e1 op e2, but e1 is evaluated only once.

Compound assignment to an enumerated type generates an error message. If the left operand is of a pointer type, the right operand must be of a pointer type or it must be a constant expression that evaluates to 0. If the left operand is of an integral type, the right operand must not be of a pointer type.


Comma Operator

The comma operator allows grouping two statements where one is expected.

Syntax

expression :

assignment-expression
expression , assignment-expression

The comma operator has left-to-right associativity. Two expressions separated by a comma are evaluated left to right. The left operand is always evaluated, and all side effects are completed before the right operand is evaluated.

Consider the expression

e1 , e2

The type and value of the expression are the type and value of e2; the result of evaluating e1 is discarded. The result is an l-value if the right operand is an l-value.

Where the comma has special meaning (for example in actual arguments to functions or aggregate initializers), the comma operator and its operands must be enclosed in parentheses. Therefore, the following function calls are not equivalent:

// Declare functions:
void Func( int, int );
void Func( int );

Func( arg1, arg2 );    // Call Func( int, int )
Func( (arg1, arg2) );  // Call Func( int )

This example illustrates the comma operator:

for ( i = j = 1; i + j < 20; i += i, j-- );

In this example, each operand of the for statement’s third expression is evaluated independently. The left operand i += i is evaluated first; then the right operand, j––, is evaluated.

func_one( x, y + 2, z );
func_two( (x--, y + 2), z );

In the function call to func_one, three arguments, separated by commas, are passed: x, y + 2, and z. In the function call to func_two, parentheses force the compiler to interpret the first comma as the sequential-evaluation operator. This function call passes two arguments to func_two. The first argument is the result of the sequential-evaluation operation (x--, y + 2), which has the value and type of the expression y + 2; the second argument is z.


Expressions with the Conditional Operator

The conditional operator (? :) is a ternary operator (it takes three operands). The conditional operator works as follows:

  • The first operand is evaluated and all side effects are completed before continuing.

  • If the first operand evaluates to true (a nonzero value), the second operand is evaluated.

  • If the first operand evaluates to false (0), the third operand is evaluated.

The result of the conditional operator is the result of whichever operand is evaluated — the second or the third. Only one of the last two operands is evaluated in a conditional expression.

Syntax

conditional-expression :

logical-or-expression
logical-or-expression ? expression : conditional-expression

Conditional expressions have no associativity. The first operand must be of integral or pointer type. The following rules apply to the second and third expressions:

  • If both expressions are of the same type, the result is of that type.

  • If both expressions are of arithmetic types, usual arithmetic conversions (covered in Arithmetic Conversions in Chapter 3) are performed to convert them to a common type.

  • If both expressions are of pointer types or if one is a pointer type and the other is a constant expression that evaluates to 0, pointer conversions are performed to convert them to a common type.

  • If both expressions are of reference types, reference conversions are performed to convert them to a common type.

  • If both expressions are of type void, the common type is type void.

  • If both expressions are of a given class type, the common type is that class type.

Any combinations of second and third operands not in the preceding list are illegal. The type of the result is the common type, and it is an l-value if both the second and third operands are of the same type and both are l-values.

For example:

(val >= 0) ? val : -val

If the condition is true, the expression evaluates to val. If not, the expression equals –val.


C++ Constant Expressions

C++ requires constant expressions — expressions that evaluate to a constant — for declarations of:

  • Array bounds

  • Selectors in case statements

  • Bit-field length specification

  • Enumeration initializers

Syntax

constant-expression :

conditional-expression

The only operands that are legal in constant expressions are:

  • Literals

  • Enumeration constants

  • Values declared as const that are initialized with constant expressions

  • sizeof expressions

Nonintegral constants must be converted (either explicitly or implicitly) to integral types to be legal in a constant expression. Therefore, the following code is legal:

const double Size = 11.0;

char chArray[(int)Size];

Explicit conversions to integral types are legal in constant expressions; all other types and derived types are illegal except when used as operands to the sizeof operator.

The comma operator and assignment operators cannot be used in constant expressions.


Expressions with Explicit Type Conversions

C++ provides implicit type conversion, as described in Chapter 3, Standard Conversions. You can also specify explicit type conversions when you need more precise control of the conversions applied.


Explicit Type Conversion Operator

C++ allows explicit type conversion using a syntax similar to the function-call syntax. A simple-type-name followed by an expression-list enclosed in parentheses constructs an object of the specified type using the specified expressions. The following example shows an explicit type conversion to type int:

int i = int( d );

The following example uses a modified version of the Point class defined in Function-Call Results.

#include <iostream.h>

class Point
{
public:
    // Define default constructor.
    Point() { _x = _y = 0; }
    // Define another constructor.
    Point( int X, int Y ) { _x = X; _y = Y; }

    // Define "accessor" functions as
    // reference types.
    unsigned& x() { return _x; }
    unsigned& y() { return _y; }
    void Show()   { cout << "x = " << _x << ", "
                         << "y = " << _y << "\n"; }
private:
    unsigned _x;
    unsigned _y;
};

void main()
{
    Point Point1, Point2;

    // Assign Point1 the explicit conversion
    //  of ( 10, 10 ).
    Point1 = Point( 10, 10 );

    // Use x() as an l-value by assigning an explicit
    //  conversion of 20 to type unsigned.
    Point1.x() = unsigned( 20 );
    Point1.Show();

    // Assign Point2 the default Point object.
    Point2 = Point();
    Point2.Show();
}

The output from this program is:

x = 20, y = 10
x = 0, y = 0

Although the preceding example demonstrates explicit type conversion using constants, the same technique works to perform these conversions on objects. The following code fragment demonstrates this:

int i = 7;
float d;

d = float( i );

Explicit type conversions can also be specified using the “cast” syntax. The previous example, rewritten using the cast syntax, is:

d = (float)i;

Both cast and function-style conversions have the same results when converting from single values. However, in the function-style syntax, you can specify more than one argument for conversion. This difference is important for user-defined types. Consider a Point class and its conversions:

struct Point
{
    Point( short x, short y ) { _x = x; _y = y; }
    ...
    short _x, _y;
};
...
Point pt = Point( 3, 10 );

The preceding example, which uses function-style conversion, shows how to convert two values (one for x and one for y) to the user-defined type Point.

Important Use the explicit type conversions with care, since they override the C++ compiler’s built-in type checking.

Syntax

cast-expression :

unary-expression
( type-name ) cast-expression

The cast notation must be used for conversions to types that do not have a simple-type-name (pointer or reference types, for example). Conversion to types that can be expressed with a simple-type-name can be written in either form. See Type Specifiers in Chapter 6 for more information about what constitutes a simple-type-name.

Type definition within casts is illegal.


Legal Conversions

You can do explicit conversions from a given type to another type if the conversion can be done using standard conversions. The results are the same. The conversions described in this section are legal; any other conversions not explicitly defined by the user (for a class type) are illegal.

A value of integral type can be explicitly converted to a pointer if the pointer is large enough to hold the integral value. A pointer that is converted to an integral value can be converted back to a pointer; its value is the same. This identity is given by the following (where p represents a pointer of any type):

p == (type *) integral-conversion( p )

With explicit conversions, the compiler does not check whether the converted value fits in the new type except when converting from pointer to integral type or vice versa.

This section describes the following conversions:

  • Converting pointer types

  • Converting the null pointer

  • Converting to a forward reference class type

  • Converting to reference types

  • Converting among pointer to member types


Converting Pointer Types

A pointer to one object type can be explicitly converted to a pointer of another object type. A pointer declared as void * is considered a pointer to any object type.

A pointer to a base class can be explicitly converted to a pointer to a derived class as long as these conditions are met:

  • There is an unambiguous conversion.

  • The base class is not declared as virtual at any point.

Because conversion to type void * can change the representation of an object, there is no guarantee that the conversion type1* void * type2* is equivalent to the conversion type1* type2* (which is a change in value only).

When such a conversion is performed, the result is a pointer to the subobject of the original object representing the base class.

See Chapter 9, Derived Classes, for more information about ambiguity and virtual base classes.

C++ allows explicit conversions of pointers to objects or functions to type void *.

Pointers to object types can be explicitly converted to pointers to functions if the function pointer type has enough bits to accommodate the pointer to object type.

A pointer to a const object can be explicitly converted to a pointer not of const type. The result of this conversion points to the original object. An object of const type, or a reference to an object of const type, can be cast to a reference to a type that is not const. The result is a reference to the original object. The original object was probably declared as const because it was to remain constant across the duration of the program. Therefore, an explicit conversion defeats this safeguard, allowing modification of such objects. The behavior in such cases is undefined.

A pointer to an object of volatile type can be cast to a pointer to a type that is not volatile. The result of this conversion refers to the original object. Similarly, an object of volatile type can be cast to a reference to a type that is not volatile.


Converting the Null Pointer

The null pointer (0) is converted into itself.


Converting to a Forward-Reference Class Type

A class that has been declared but not yet defined (a forward reference) can be used in a pointer cast. In this case, the compiler returns a pointer to the original object, not to a subobject as it might if the class’s relationships were known.


Converting to Reference Types

Any object whose address can be converted to a given pointer type can also be converted to the analogous reference type. For example, any object whose address can be converted to type char * can also be converted to type char &. No constructors or class conversion functions are called to make a conversion to a reference type.

Objects or values can be converted to class-type objects only if a constructor or conversion operator has been provided specifically for this purpose. For more information about these user-defined functions, see Conversion Constructors in Chapter 11.

Conversion of a reference to a base class, to a reference to a derived class (and vice versa) is done the same way as for pointers.

A cast to a reference type results in an l-value. The results of casts to other types are not l-values. Operations performed on the result of a pointer or reference cast are still performed on the original object.


Converting Among Pointer-to-Member Types

A pointer to a member can be converted to a different pointer-to-member type subject to these rules: Either the pointers must both be pointers to members in the same class or they must be pointers to members of classes, one of which is derived unambiguously from the other. When converting pointer-to-member functions, the return and argument types must match.


Expressions with Pointer-to-Member Operators

The pointer-to-member operators, .* and –>*, return the value of a specific class member for the object specified on the left side of the expression. The following example shows how to use these operators:

#include <iostream.h>

class Window
{
public:
    void Paint(); // Causes window to repaint.
    int WindowId;
};

// Define derived types pmfnPaint and pmWindowId.
// These types are pointers to members Paint() and
// WindowId, respectively.
void (Window::*pmfnPaint)() = &Window::Paint;
int Window::*pmWindowId = &Window::WindowId;

void main()
{
    Window AWindow;
    Window *pWindow = new Window;
// Invoke the Paint function normally, then use pointer to member.
    AWindow.Paint();
    (AWindow.*pmfnPaint)();

    pWindow->Paint();
    (pWindow->*pmfnPaint)(); // Parentheses required since * binds
                             //  less tightly than the function call.

    int Id;
    // Retrieve window id.
    Id = AWindow.*pmWindowId;
    Id = pWindow->*pmWindowId;
}

In the preceding example, a pointer to a member, pmfnPaint, is used to invoke the member function Paint. Another pointer to a member, pmWindowId, is used to access the WindowId member.

Syntax

pm-expression :

cast-expression
pm-expression .* cast-expression
pm-expression –>* cast-expression

The binary operator .* combines its first operand, which must be an object of class type, with its second operand, which must be a pointer-to-member type.

The binary operator –>* combines its first operand, which must be a pointer to an object of class type, with its second operand, which must be a pointer-to-member type.

In an expression containing the .* operator, the first operand must be of the class type of, and be accessible to, the pointer to member specified in the second operand or of an accessible type unambiguously derived from and accessible to that class.

In an expression containing the –>* operator, the first operand must be of the type “pointer to the class type” of the type specified in the second operand, or it must be of a type unambiguously derived from that class.

Consider the following classes and program fragment:

class BaseClass
{
public:
    BaseClass(); // Base class constructor.
    void Func1();
};

// Declare a pointer to member function Func1.
void (BaseClass::*pmfnFunc1)() = &BaseClass::Func1;

class Derived : public BaseClass
{
public:
    Derived();  // Derived class constructor.
    void Func2();
};

// Declare a pointer to member function Func2.
void (Derived::*pmfnFunc2)() = &Derived::Func2;

void main()
{
    BaseClass ABase;
    Derived ADerived;

    (ABase.*pmfnFunc1)();    // OK: defined for BaseClass.
    (ABase.*pmfnFunc2)();    // Error: cannot use base class to
                             //  access pointers to members of
                             //  derived classes.
    (ADerived.*pmfnFunc1)(); // OK: Derived is unambiguously
                             //  derived from BaseClass.
    (ADerived.*pmfnFunc2)(); // OK: defined for Derived.
}

The result of the .* or –>* pointer-to-member operators is an object or function of the type specified in the declaration of the pointer to member. So, in the preceding example, the result of the expression ADerived.*pmfnFunc1() is a pointer to a function that returns void. This result is an l-value if the second operand is an l-value.

Note If the result of one of the pointer-to-member operators is a function, then the result can be used only as an operand to the function call operator.


Semantics of Expressions

This section explains when, and in what order, expressions are evaluated.

The following topics are included:

  • Order of evaluation

  • Sequence points

  • Ambiguous expressions

  • Notation in expressions


Order of Evaluation

This section discusses the order in which expressions are evaluated but does not explain the syntax or the semantics of the operators in these expressions. The earlier sections in this chapter provide a complete reference for each of these operators.

Expressions are evaluated according to the precedence and grouping of their operators. (Table 1.1 in Chapter 1, Lexical Conventions, shows the relationships the C++ operators impose on expressions.) Consider this example:

#include <iostream.h>

void main()
{
    int a = 2, b = 4, c = 9;

    cout << a + b * c << "\n";
    cout << a + (b * c) << "\n";
    cout << (a + b) * c << "\n";
}

The output from the preceding code is:

38
38
54

Figure 4.1 Expression-Evaluation Order

The order in which the expression shown in Figure 4.1 is evaluated is determined by the precedence and associativity of the operators:

  1. Multiplication (*) has the highest precedence in this expression; hence the subexpression b * c is evaluated first.

  2. Addition (+) has the next highest precedence, so a is added to the product of b and c.

  3. Left shift (<<) has the lowest precedence in the expression, but there are two occurrences. Because the left-shift operator groups left-to-right, the left subexpression is evaluated first and then the right one.

When parentheses are used to group the subexpressions, they alter the precedence and also the order in which the expression is evaluated, as shown in Figure 4.2.

Figure 4.2 Expression-Evaluation Order with Parentheses

Expressions such as those in Figure 4.2 are evaluated purely for their side effects — in this case, to transfer information to the standard output device.

Note The left-shift operator is used to insert an object in an object of class ostream. It is sometimes called the “insertion” operator when used with iostream.


C++ Sequence Points

An expression can modify an object’s value only once between consecutive “sequence points.”

Microsoft Specific

The C++ language definition does not currently specify sequence points. Microsoft C++ uses the same sequence points as ANSI C for any expression involving C operators and not involving overloaded operators. When operators are overloaded, the semantics change from operator sequencing to function-call sequencing. Microsoft C++ uses the following sequence points:

  • Left operand of the logical AND operator (&&). The left operand of the logical AND operator is completely evaluated and all side effects completed before continuing. There is no guarantee that the right operand of the logical AND operator will be evaluated.

  • Left operand of the logical OR operator (||). The left operand of the logical OR operator is completely evaluated and all side effects completed before continuing. There is no guarantee that the right operand of the logical OR operator will be evaluated.

  • Left operand of the comma operator. The left operand of the comma operator is completely evaluated and all side effects completed before continuing. Both operands of the comma operator are always evaluated.

  • Function-call operator. The function-call expression and all arguments to a function, including default arguments, are evaluated and all side effects completed prior to entry to the function. There is no specified order of evaluation among the arguments or the function-call expression.

  • First operand of the conditional operator. The first operand of the conditional operator is completely evaluated and all side effects completed before continuing.

  • The end of a full initialization expression, such as the end of an initialization in a declaration statement.

  • The expression in an expression statement. Expression statements consist of an optional expression followed by a semicolon (;). The expression is completely evaluated for its side effects.

  • The controlling expression in a selection (if or switch) statement. The expression is completely evaluated and all side effects completed before the code dependent on the selection is executed.

  • The controlling expression of a while or do statement. The expression is completely evaluated and all side effects completed before any statements in the next iteration of the while or do loop are executed.

  • Each of the three expressions of a for statement. Each expression is completely evaluated and all side effects completed before moving to the next expression.

  • The expression in a return statement. The expression is completely evaluated and all side effects completed before control returns to the calling function.

END Microsoft Specific


Ambiguous Expressions

Certain expressions are ambiguous in their meaning. These expressions occur most frequently when an object’s value is modified more than once in the same expression. These expressions rely on a particular order of evaluation where the language does not define one. Consider the following example:

int i = 7;

func( i, ++i );

The C++ language does not guarantee the order in which arguments to a function call are evaluated. Therefore, in the preceding example, func could receive the values 7 and 8, or 8 and 8 for its parameters, depending on whether the parameters are evaluated from left to right or from right to left.


Notation in Expressions

The C++ language specifies certain compatibilities when specifying operands. Table 4.5 shows the types of operands acceptable to operators that require operands of type type.

Table 4.5 Operand Types Acceptable to Operators

Type Expected | Types Allowed
type | const type volatile type type& const type& volatile type& volatile const type volatile const type&
type* | type* const type* volatile type* volatile const
const type | type const type const type&
volatile type | type volatile type volatile type&

Because the preceding rules can always be used in combination, a const pointer to a volatile object can be supplied where a pointer is expected.


Casting

The C++ language provides that if a class is derived from a base class containing virtual functions, a pointer to that base class type can be used to call the implementations of the virtual functions residing in the derived class object. A class containing virtual functions is sometimes called a “polymorphic class.”

Since a derived class completely contains the definitions of all the base classes from which it is derived, it is safe to cast a pointer up the class hierarchy to any of these base classes. Given a pointer to a base class, it might be safe to cast the pointer down the hierarchy. It is safe if the object being pointed to is actually of a type derived from the base class. In this case, the actual object is said to be the “complete object.” The pointer to the base class is said to point to a “subobject” of the complete object. For example, consider the class hierarchy shown in Figure 4.3:

Figure 4.3 Class Hierarchy

An object of type C could be visualized as shown in Figure 4.4:

Figure 4.4 Class C with B Subobject and A Subobject

Given an instance of class C, there is a B subobject and an A subobject. The instance of C, including the A and B subobjects, is the “complete object.”

Using run-time type information, it is possible to check whether a pointer actually points to a complete object and can be safely cast to point to another object in its hierarchy. The dynamic_cast operator can be used to make these types of casts. It also performs the run-time check necessary to make the operation safe.


Casting Operators

There are several casting operators specific to the C++ language. These operators are intended to remove some of the ambiguity and danger inherent in old style C language casts. These operators are:

  • dynamic_cast Used for conversion of polymorphic types.

  • static_cast Used for conversion of nonpolymorphic types.

  • const_cast Used to remove the const, volatile, and __unaligned attributes.

  • reinterpret_cast Used for simple reinterpretation of bits.

Use const_cast and reinterpret_cast as a last resort, since these operators present the same dangers as old style casts. However, they are still necessary in order to completely replace old style casts.


dynamic_cast Operator

The expression dynamic_cast<type-id>( expression ) converts the operand expression to an object of type type-id. The type-id must be a pointer or a reference to a previously defined class type or a “pointer to void”. The type of expression must be a pointer if type-id is a pointer, or an l-value if type-id is a reference.

Syntax

dynamic_cast < type-id > ( expression )

If type-id is a pointer to an unambiguous accessible direct or indirect base class of expression, a pointer to the unique subobject of type type-id is the result. For example:

class B { ... };
class C : public B { ... };
class D : public C { ... };

void f(D* pd)
{
   C* pc = dynamic_cast<C*>(pd);   // ok: C is a direct base class
                           // pc points to C subobject of pd

   B* pb = dynamic_cast<B*>(pd);   // ok: B is an indirect base class
                           // pb points to B subobject of pd
   ...
}

This type of conversion is called an “upcast” because it moves a pointer up a class hierarchy, from a derived class to a class it is derived from. An upcast is an implicit conversion.

If type-id is void*, a run-time check is made to determine the actual type of expression. The result is a pointer to the complete object pointed to by expression. For example:

class A { ... };

class B { ... };

void f()
{
   A* pa = new A;
   B* pb = new B;
   void* pv = dynamic_cast<void*>(pa);
   // pv now points to an object of type A
   ...
   pv = dynamic_cast<void*>(pb);
   // pv now points to an object of type B
}

If type-id is not void*, a run-time check is made to see if the object pointed to by expression can be converted to the type pointed to by type-id.

If the type of expression is a base class of the type of type-id, a run-time check is made to see if expression actually points to a complete object of the type of type-id. If this is true, the result is a pointer to a complete object of the type of type-id. For example:

class B { ... };
class D : public B { ... };

void f()
{
   B* pb = new D;               // unclear but ok
   B* pb2 = new B;

   D* pd = dynamic_cast<D*>(pb);      // ok: pb actually points to a D
   ...
   D* pd2 = dynamic_cast<D*>(pb2);   //error: pb2 points to a B, not a D
                              // pd2 == NULL
   ...
}

This type of conversion is called a “downcast” because it moves a pointer down a class hierarchy, from a given class to a class derived from it.

In cases of multiple inheritance, possibilities for ambiguity are introduced. Consider the class hierarchy shown in Figure 4.5:

Figure 4.5 Class Hierarchy Showing Multiple Inheritance

A pointer to an object of type D can be safely cast to B or C. However, if D is cast to point to an A object, which instance of A would result? This would result in an ambiguous casting error. To get around this problem, you can perform two unambiguous casts. For example:

void f()
{
   D* pd = new D;
   A* pa = dynamic_cast<A*>(pd);      // error: ambiguous
   B* pb = dynamic_cast<B*>(pd);      // first cast to B
   A* pa2 = dynamic_cast<A*>(pb);   // ok: unambiguous
}

Further ambiguities can be introduced when you use virtual base classes. Consider the class hierarchy shown in Figure 4.6:

Figure 4.6 Class Hierarchy Showing Virtual Base Classes

In this hierarchy, A is a virtual base class. See Virtual Base Classes for the definition of a virtual base class. Given an instance of class E and a pointer to the A subobject, a dynamic_cast to a pointer to B will fail due to ambiguity. You must first cast back to the complete E object, then work your way back up the hierarchy, in an unambiguous manner, to reach the correct B object.

Consider the class hierarchy shown in Figure 4.7:

Figure 4.7 Class Hierarchy Showing Duplicate Base Classes

Given an object of type E and a pointer to the D subobject, to navigate from the D subobject to the left-most A subobject, three conversions can be made. You can perform a dynamic_cast conversion from the D pointer to an E pointer, then a conversion (either dynamic_cast or an implicit conversion) from E to B, and finally an implicit conversion from B to A. For example:

void f(D* pd)
{
   E* pe = dynamic_cast<E*>(pd);
   B* pb = pe;      // upcast, implicit conversion
   A* pa = pb;      // upcast, implicit conversion
}

The dynamic_cast operator can also be used to perform a “cross cast.” Using the same class hierarchy, it is possible to cast a pointer, for example, from the B subobject to the D subobject, as long as the complete object is of type E.

Considering cross casts, it is actually possible to do the conversion from a pointer to D to a pointer to the left-most A subobject in just two steps. You can perform a cross cast from D to B, then an implicit conversion from B to A. For example:

void f(D* pd)
{
   B* pb = dynamic_cast<B*>(pd);      // cross cast
   A* pa = pb;                  // upcast, implicit conversion
}

A null pointer value is converted to the null pointer value of the destination type by dynamic_cast.

When you use dynamic_cast < type-id > ( expression ), if expression cannot be safely converted to type type-id, the run-time check causes the cast to fail. For example:

class A { ... };

class B { ... };

void f()
{
   A* pa = new A;
   B* pb = dynamic_cast<B*>(pa);      // fails, not safe;
                              // B not derived from A
   ...
}

The value of a failed cast to pointer type is the null pointer. A failed cast to reference type throws a bad_cast exception.


bad_cast Exception

The dynamic_cast operator throws a bad_cast exception as the result of a failed cast to a reference type. The interface for bad_cast is:

class bad_cast : public logic {
public:
   bad_cast(const __exString& what_arg) : logic(what_arg) {}
   void raise() { handle_raise(); throw *this; }
   // virtual __exString what() const;   //inherited
};


static_cast Operator

The expression static_cast < type-id > ( expression ) converts expression to the type of type-id based solely on the types present in the expression. No run-time type check is made to ensure the safety of the conversion.

Syntax

static_cast < type-id > ( expression )

The static_cast operator can be used for operations such as converting a pointer to a base class to a pointer to a derived class. Such conversions are not always safe. For example:

class B { ... };

class D : public B { ... };

void f(B* pb, D* pd)
{
    D* pd2 = static_cast<D*>(pb);        // not safe, pb may
                                         // point to just B

    B* pb2 = static_cast<B*>(pd);        // safe conversion
    ...
}

In contrast to dynamic_cast, no run-time check is made on the static_cast conversion of pb. The object pointed to by pb may not be an object of type D, in which case the use of *pd2 could be disastrous. For instance, calling a function that is a member of the D class, but not the B class, could result in an access violation.

The dynamic_cast and static_cast operators move a pointer throughout a class hierarchy. However, static_cast relies exclusively on the information provided in the cast statement and can therefore be unsafe. For example:

class B { ... };
class D : public B { ... };

void f(B* pb)
{
   D* pd1 = dynamic_cast<D*>(pb);
   D* pd2 = static_cast<D*>(pb);
}

If pb really points to an object of type D, then pd1 and pd2 will get the same value. They will also get the same value if pb == 0.

If pb points to an object of type B and not to the complete D class, then dynamic_cast will know enough to return zero. However, static_cast relies on the programmer’s assertion that pb points to an object of type D and simply returns a pointer to that supposed D object.

Consequently, static_cast can do the inverse of implicit conversions, in which case the results are undefined. It is left to the programmer to ensure that the results of a static_cast conversion are safe.

This behavior also applies to types other than class types. For instance, static_cast can be used to convert from an int to a char. However, the resulting char may not have enough bits to hold the entire int value. Again, it is left to the programmer to ensure that the results of a static_cast conversion are safe.

The static_cast operator can also be used to perform any implicit conversion, including standard conversions and user-defined conversions. For example:

typedef unsigned char BYTE

void f()
{
   char ch;
   int i = 65;
   float f = 2.5;
   double dbl;

   ch = static_cast<char>(i);         // int to char
   dbl = static_cast<double>(f);         // float to double
   ...
   i = static_cast<BYTE>(ch);
   ...
}

The static_cast operator can explicitly convert an integral value to an enumeration type. If the value of the integral type does not fall within the range of enumeration values, the resulting enumeration value is undefined.

The static_cast operator converts a null pointer value to the null pointer value of the destination type.

Any expression can be explicitly converted to type void by the static_cast operator. The destination void type can optionally include the const, volatile, or __unaligned attribute.

The static_cast operator cannot cast away the const, volatile, or __unaligned attributes. See const_cast Operator for information on removing these attributes.


const_cast Operator

The const_cast operator can be used to remove the const, volatile, and __unaligned attribute(s) from a class.

Syntax

const_cast < type-id > ( expression )

A pointer to any object type or a pointer to a data member can be explicitly converted to a type that is identical except for the const, volatile, and __unaligned qualifiers. For pointers and references, the result will refer to the original object. For pointers to data members, the result will refer to the same member as the original (uncast) pointer to data member. Depending on the type of the referenced object, a write operation through the resulting pointer, reference, or pointer to data member might produce undefined behavior.

The const_cast operator converts a null pointer value to the null pointer value of the destination type.


reinterpret_cast Operator

The reinterpret_cast operator allows any pointer to be converted into any other pointer type. It also allows any integral type to be converted into any pointer type and vice versa. Misuse of the reinterpret_cast operator can easily be unsafe. Unless the desired conversion is inherently low-level, you should use one of the other cast operators.

Syntax

reinterpret_cast < type-id > ( expression )

The reinterpret_cast operator can be used for conversions such as char* to int*, or One_class* to Unrelated_class*, which are inherently unsafe.

The result of a reinterpret_cast cannot safely be used for anything other than being cast back to its original type. Other uses are, at best, nonportable.

The reinterpret_cast operator cannot cast away the const, volatile, or __unaligned attributes. See const_cast Operator for information on removing these attributes.

The reinterpret_cast operator converts a null pointer value to the null pointer value of the destination type.


Run-Time Type Information

Run-time type information (RTTI) is a mechanism that allows the type of an object to be determined during program execution. RTTI was added to the C++ language because many vendors of class libraries were implementing this functionality themselves. This caused incompatibilities between libraries. Thus, it became obvious that support for run-time type information was needed at the language level.

For the sake of clarity, this discussion of RTTI is almost completely restricted to pointers. However, the concepts discussed also apply to references.

There are three main C++ language elements to run-time type information:

  • The dynamic_cast operator.
    Used for conversion of polymorphic types. See dynamic_cast Operator for more information.

  • The typeid operator.
    Used for identifying the exact type of an object.

  • The type_info class.
    Used to hold the type information returned by the typeid operator.


typeid Operator

The typeid operator allows the type of an object to be determined at run time.

Syntax

typeid( type-id )

typeid( expression )

The result of a typeid expression is a const type_info&. The value is a reference to a type_info object that represents either the type-id or the type of the expression, depending on which form of typeid is used. See type_info Class for more information.

The typeid operator does a run-time check when applied to an l-value of a polymorphic class type, where the true type of the object cannot be determined by the static information provided. Such cases are:

  • A reference to a class

  • A pointer, dereferenced with *

  • A subscripted pointer (i.e. [ ]). (Note that it is generally not safe to use a subscript with a pointer to a polymorphic type.)

If the expression points to a base class type, yet the object is actually of a type derived from that base class, a type_info reference for the derived class is the result. The expression must point to a polymorphic type, that is, a class with virtual functions. Otherwise, the result is the type_info for the static class referred to in the expression. Further, the pointer must be dereferenced so that the object it points to is used. Without dereferencing the pointer, the result will be the type_info for the pointer, not what it points to. For example:

class Base { ... };

class Derived : public Base { ... };

void f()
{
   Derived* pd = new Derived;
   Base* pb = pd;
   ...
   const type_info& t = typeid(pb);      // t holds pointer type_info
   const type_info& t1 = typeid(*pb);      // t1 holds Derived info
   ...
}

If the expression is dereferencing a pointer, and that pointer’s value is zero, typeid throws a bad_typeid exception. If the pointer does not point to a valid object, a __non_rtti_object exception is thrown.

If the expression is neither a pointer nor a reference to a base class of the object, the result is a type_info reference representing the static type of the expression.


bad_typeid Exception

Under some circumstances, the typeid operator throws a bad_typeid exception. The interface for bad_typeid is:

class bad_typeid : public logic {
public:
    bad_typeid(const char * what_arg) : logic(what_arg) {}
    void raise()    { handle_raise(); throw *this; }
    // virtual __exString what() const;    //inherited
};

See typeid Operator for more information.


type_info Class

The type_info class describes type information generated within the program by the compiler. Objects of this class effectively store a pointer to a name for the type. The type_info class also stores an encoded value suitable for comparing two types for equality or collating order. The encoding rules and collating sequence for types are unspecified and may differ between programs.

The typeinfo.h header file must be included in order to use the type_info class.

class type_info {
public:
   virtual ~type_info();
   int operator==(const type_info& rhs) const;
   int operator!=(const type_info& rhs) const;
   int before(const type_info& rhs) const;
   const char* name() const;
   const char* raw_name() const;
private:
   ...
};

The operators == and != can be used to compare for equality and inequality with other type_info objects, respectively.

There is no link between the collating order of types and inheritance relationships. Use the type_info::before member function to determine the collating sequence of types. There is no guarantee that type_info::before will yield the same result in different programs or even different runs of the same program. In this manner, type_info::before is similar to the address-of (&) operator.

The type_info::name member function returns a const char* to a null-terminated string representing the human-readable name of the type. The memory pointed to is cached and should never be directly deallocated.

The type_info::raw_name member function returns a const char* to a null-terminated string representing the decorated name of the object type. The name is actually stored in its decorated form to save space. Consequently, this function is faster than type_info::name because it doesn’t need to undecorate the name. The string returned by the type_info::raw_name function is useful in comparison operations but is not readable. If you need a human-readable string, use the type_info::name function instead.

Type information is generated for polymorphic classes only if the /GR (Enable Run-Time Type Information) compiler option is specified.


Statements

C++ statements are the program elements that control how and in what order objects are manipulated. This chapter includes:

  • Overview

  • Labeled Statements

  • Categories of Statements
    • Expression statements. These statements evaluate an expression for its side effects or for its return value.

    • Null statements. These statements can be provided where a statement is required by the C++ syntax but where no action is to be taken.

    • Compound statements. These statements are groups of statements enclosed in curly braces ({ }). They can be used wherever the grammar calls for a single statement.

    • Selection statements. These statements perform a test; they then execute one section of code if the test evaluates to true (nonzero). They may execute another section of code if the test evaluates to false.

    • Iteration statements. These statements provide for repeated execution of a block of code until a specified termination criterion is met.

    • Jump statements. These statements either transfer control immediately to another location in the function or return control from the function.

    • Declaration statements. Declarations introduce a name into a program. (Chapter 6, Declarations, provides more detailed information about declarations.)

    • Exception handling statements, which include C++ exception handling (try, throw, catch) and structured exception handling (__try/__except, __try/__finally). The try-except statement provides a method to gain control of a program when events that normally terminate execution occur. The try-finally and leave statements provide a method to guarantee execution of cleanup code when execution of a block of code is interrupted.


Overview of C++ Statements

C++ statements are executed sequentially, except when an expression statement, a selection statement, an iteration statement, or a jump statement specifically modifies that sequence.

Syntax

statement:

labeled-statement
expression-statement
compound-statement
selection-statement
iteration-statement
jump-statement
declaration-statement
try-throw-catch

In most cases, the C++ statement syntax is identical to that of ANSI C. The primary difference between the two is that in C, declarations are allowed only at the start of a block; C++ adds the declaration-statement, which effectively removes this restriction. This enables you to introduce variables at a point in the program where a precomputed initialization value can be calculated.

Declaring variables inside blocks also allows you to exercise precise control over the scope and lifetime of those variables.


Labeled Statements

To transfer program control directly to a given statement, the statement must be labeled. See Using Labels with the goto Statement and Using Labels in the case Statement.

Syntax

labeled-statement:

identifier : statement
case constant-expression : statement
default : statement


Using Labels with the goto Statement

The appearance of an identifier label in the source program declares a label. Only a goto statement can transfer control to an identifier label. The following code fragment illustrates use of the goto statement and an identifier label to escape a tightly nested loop:

for( p = 0; p < NUM_PATHS; ++p )
{
    NumFiles = FillArray( pFileArray, pszFNames )
    for( i = 0; i < NumFiles; ++i )
    {
        if( (pFileArray[i] = fopen( pszFNames[i], "r" )) == NULL )
            goto FileOpenError;
        // Process the files that were opened.
    }
}

FileOpenError:
    cerr << "Fatal file open error. Processing interrupted.\n" );

In the preceding example, the goto statement transfers control directly to the statement that prints an error message if an unknown file-open error occurs.

A label cannot appear by itself but must always be attached to a statement. If a label is needed by itself, place a null statement after the label.

The label has function scope and cannot be redeclared within the function. However, the same name can be used as a label in different functions.


Using Labels in the case Statement

Labels that appear after the case keyword cannot also appear outside a switch statement. (This restriction also applies to the default keyword.) The following code fragment shows the correct use of case labels:

// Sample Microsoft Windows message processing loop.
switch( msg )
{
case WM_TIMER:    // Process timer event.
    SetClassWord( hWnd, GCW_HICON, ahIcon[nIcon++] );
    ShowWindow( hWnd, SW_SHOWNA );
    nIcon %= 14;
    Yield();
    break;

case WM_PAINT:
    // Obtain a handle to the device context.
    // BeginPaint will send WM_ERASEBKGND if appropriate.

    memset( &ps, 0x00, sizeof(PAINTSTRUCT) );
    hDC = BeginPaint( hWnd, &ps );

    // Inform Windows that painting is complete.

    EndPaint( hWnd, &ps );
    break;

case WM_CLOSE:
    // Close this window and all child windows.

    KillTimer( hWnd, TIMER1 );
    DestroyWindow( hWnd );
    if( hWnd == hWndMain )
        PostQuitMessage( 0 );  // Quit the application.
    break;

default:
    // This choice is taken for all messages not specifically
    //  covered by a case statement.

    return DefWindowProc( hWnd, Message, wParam, lParam );
    break;
}


Expression Statement

Expression statements cause expressions to be evaluated. No transfer of control or iteration takes place as a result of an expression statement.

Syntax

expression-statement:

expressionopt ;

All expressions in an expression statement are evaluated and all side effects are completed before the next statement is executed. The most common expression statements are assignments and function calls. C++ also provides a null statement.


The C++ Null Statement

The “null statement” is an expression statement with the expression missing. It is useful when the syntax of the language calls for a statement but no expression evaluation. It consists of a semicolon.

Null statements are commonly used as placeholders in iteration statements or as statements on which to place labels at the end of compound statements or functions.

The following code fragment shows how to copy one string to another and incorporates the null statement:

char *strcpy( char *Dest, const char *Source )
{
    char *DestStart = Dest;

    // Assign value pointed to by Source to
    //  Dest until the end-of-string 0 is
    //  encountered.
    while( *Dest++ = *Source++ )
        ;                          // Null statement.

    return DestStart;
}


Compound Statements (Blocks)

A compound statement consists of zero or more statements enclosed in curly braces ({ }). A compound statement can be used anywhere a statement is expected. Compound statements are commonly called “blocks.”

Syntax

compound-statement :

{ statement-listopt }

statement-list :

statement
statement-list statement

The following example uses a compound statement as the statement part of the if statement (see The if Statement for details about the syntax):

if( Amount > 100 )
{
    cout << "Amount was too large to handle\n";
    Alert();
}
else
    Balance -= Amount;

Note Because a declaration is a statement, a declaration can be one of the statements in the statement-list. As a result, names declared inside a compound statement, but not explicitly declared as static, have local scope and (for objects) lifetime. See Scope in Chapter 2 for details about treatment of names with local scope.


Selection Statements

The C++ selection statements, if and switch, provide a means to conditionally execute sections of code.

Syntax

selection-statement:

if ( expression ) statement
if ( expression ) statement else statement
switch ( expression ) statement


The C++ if Statement

The if statement evaluates the expression enclosed in parentheses. The expression must be of arithmetic or pointer type, or it must be of a class type that defines an unambiguous conversion to an arithmetic or pointer type. (For information about conversions, see Chapter 3, Standard Conversions.)

In both forms of the if syntax, if the expression evaluates to a nonzero value (true), the statement dependent on the evaluation is executed; otherwise, it is skipped.

In the if...else syntax, the second statement is executed if the result of evaluating the expression is zero.

The else clause of an if...else statement is associated with the closest previous if statement that does not have a corresponding else statement. The following code fragment demonstrates how this works:

if( condition1 == true )
    if( condition2 == true )
        cout << "condition1 true; condition2 true\n";
    else
        cout << "condition1 true; condition2 false\n";
else
    cout << "condition 1 false\n";

Many programmers use curly braces ({ }) to explicitly clarify the pairing of complicated if and else clauses, such as in the following example:

if( condition1 == true )
{
    if( condition1 == true )
        cout << "condition1 true; condition2 true\n";
    else
        cout << "condition1 true; condition2 false\n";
}
else
    cout << "condition 1 false\n";

Although the braces are not strictly necessary, they clarify the pairing between if and else statements.


The C++ switch Statement

The C++ switch statement allows selection among multiple sections of code, depending on the value of an expression. The expression enclosed in parentheses, the “controlling expression,” must be of an integral type or of a class type for which there is an unambiguous conversion to integral type. Integral promotion is performed as described in Integral Promotions in Chapter 3.

The switch statement causes an unconditional jump to, into, or past the statement that is the “switch body,” depending on the value of the controlling expression, the values of the case labels, and the presence or absence of a default label. The switch body is normally a compound statement (although this is not a syntactic requirement). Usually, some of the statements in the switch body are labeled with case labels or with the default label. Labeled statements are not syntactic requirements, but the switch statement is meaningless without them. The default label can appear only once.

Syntax

case constant-expression : statement

default : statement

The constant-expression in the case label is converted to the type of the controlling expression and is then compared for equality. In a given switch statement, no two constant expressions in case statements can evaluate to the same value. The behavior is shown in Table 5.1.

Table 5.1 Switch Statement Behavior

Condition | Action
Converted value matches that of the promoted controlling expression. | Control is transferred to the statement following that label.
None of the constants match the constants in the case labels; default label is present. | Control is transferred to the default label.
None of the constants match the constants in the case labels; default label is not present. | Control is transferred to the statement after the switch statement.

An inner block of a switch statement can contain definitions with initializations as long as they are reachable — that is, not bypassed by all possible execution paths. Names introduced using these declarations have local scope. The following code fragment shows how the switch statement works:

switch( tolower( *argv[1] ) )
{
    // Error. Unreachable declaration.
    char szChEntered[] = "Character entered was: ";

case 'a' :
    {
    // Declaration of szChEntered OK. Local scope.
    char szChEntered[] = "Character entered was: ";
    cout << szChEntered << "a\n";
    }
    break;

case 'b' :
    // Value of szChEntered undefined.
    cout << szChEntered << "b\n";
    break;

default:
    // Value of szChEntered undefined.
    cout << szChEntered << "neither a nor b\n";
    break;
}

A switch statement can be nested. In such cases, case or default labels associate with the most deeply nested switch statements that enclose them. For example:

switch( msg )
{
case WM_COMMAND:      // Windows command. Find out more.
    switch( wParam )
    {
    case IDM_F_NEW:   // File New menu command.
        delete wfile;
        wfile = new WinAppFile;
        break;
    case IDM_F_OPEN:  // File Open menu command.
        wfile->FileOpenDlg();
        break;
    ...
    }
case WM_CREATE:       // Create window.
    ...
    break;
case WM_PAINT:        // Window needs repainting.
    ...
    break;
default:
    return DefWindowProc( hWnd, Message, wParam, lParam );
}

The preceding code fragment from a Microsoft Windows® message loop shows how switch statements can be nested. The switch statement that selects on the value of wParam is executed only if msg is WM_COMMAND. The case labels for menu selections, IDM_F_NEW and IDM_F_OPEN, associate with the inner switch statement.

Control is not impeded by case or default labels. To stop execution at the end of a part of the compound statement, insert a break statement. This transfers control to the statement after the switch statement. This example demonstrates how control “drops through” unless a break statement is used:

BOOL fClosing = FALSE;

...

switch( wParam )
{
case IDM_F_CLOSE:       // File close command.
    fClosing = TRUE;
    // fall through

case IDM_F_SAVE:        // File save command.
    if( document->IsDirty() )
        if( document->Name() == "UNTITLED" )
            FileSaveAs( document );
        else
            FileSave( document );

    if( fClosing )
        document->Close();

    break;
}

The preceding code shows how to take advantage of the fact that case labels do not impede the flow of control. If the switch statement transfers control to IDM_F_SAVE, fClosing is FALSE. Therefore, after the file is saved, the document is not closed. However, if the switch statement transfers control to IDM_F_CLOSE, fClosing is set to TRUE, and the code to save a file is executed.


Iteration Statements

Iteration statements cause statements (or compound statements) to be executed zero or more times, subject to some loop-termination criteria. When these statements are compound statements, they are executed in order, except when either the break statement or the continue statement is encountered. (For a description of these statements, see The break Statement and The continue Statement.)

C++ provides three iteration statements — while, do, and for. Each of these iterates until its termination expression evaluates to zero (false), or until loop termination is forced with a break statement. Table 5.2 summarizes these statements and their actions; each is discussed in detail in the sections that follow.

Table 5.2 C++ Iteration Statements

Statement | Evaluated At | Initialization | Increment
while | Top of loop | No | No
do | Bottom of loop | No | No
for | Top of loop | Yes | Yes

Syntax

iteration-statement :

while ( expression ) statement
do statement while ( expression ) ;
for ( for-init-statement expressionopt ; expressionopt ) statement

for-init-statement :

expression-statement
declaration-statement

The statement part of an iteration statement cannot be a declaration. However, it can be a compound statement containing a declaration.


The C++ while Statement

The while statement executes a statement repeatedly until the termination condition (the expression) specified evaluates to zero. The test of the termination condition takes place before each execution of the loop; therefore, a while loop executes zero or more times, depending on the value of the termination expression. The following code uses a while loop to trim trailing spaces from a string:

char *trim( char *szSource )
{
    char *pszEOS;

    // Set pointer to end of string to point to the character just
    //  before the 0 at the end of the string.
    pszEOS = szSource + strlen( szSource ) - 1;

    while( pszEOS >= szSource && *pszEOS == ' ' )
        *pszEOS-- = '\0';

    return szSource;
}

The termination condition is evaluated at the top of the loop. If there are no trailing spaces, the loop never executes.

The expression must be of an integral type, a pointer type, or a class type with an unambiguous conversion to an integral or pointer type.


The do Statement

The do statement executes a statement repeatedly until the specified termination condition (the expression) evaluates to zero. The test of the termination condition is made after each execution of the loop; therefore, a do loop executes one or more times, depending on the value of the termination expression. The following function uses the do statement to wait for the user to press a specific key:

void WaitKey( char ASCIICode )
{
    char chTemp;

    do
    {
        chTemp = _getch();
    }
    while( chTemp != ASCIICode );
}

A do loop rather than a while loop is used in the preceding code — with the do loop, the _getch function is called to get a keystroke before the termination condition is evaluated. This function can be written using a while loop, but not as concisely:

void WaitKey( char ASCIICode )
{
    char chTemp;

    chTemp = _getch();

    while( chTemp != ASCIICode )
    {
        chTemp = _getch();
    }
}

The expression must be of an integral type, a pointer type, or a class type with an unambiguous conversion to an integral or pointer type.


The C++ for Statement

The for statement can be divided into three separate parts, as shown in Table 5.3.

Table 5.3 for Loop Elements

Syntax Name | When Executed | Contents
for-init-statement | Before any other element of the for statement or the substatement. | Often used to initialize loop indices. It can contain expressions or declarations.
expression1 | Before execution of a given iteration of the loop, including the first iteration. | An expression that evaluates to an integral type or a class type that has an unambiguous conversion to an integral type.
expression2 | At the end of each iteration of the loop; expression1 is tested after expression2 is evaluated. | Normally used to increment loop indices.

The for-init-statement is commonly used to declare and initialize loop-index variables. The expression1 is often used to test for loop-termination criteria. The expression2 is commonly used to increment loop indices.

The for statement executes the statement repeatedly until expression1 evaluates to zero. The for-init-statement, expression1, and expression2 fields are all optional.

The following for loop:

for( for-init-statement; expression1; expression2 )
{
    // Statements
}

is equivalent to the following while loop:

for-init-statement;
while( expression1 )
{
    // Statements
    expression2;
}

A convenient way to specify an infinite loop using the for statement is:

for( ; ; )
{
    // Statements to be executed.
}

This is equivalent to:

while( 1 )
{
    // Statements to be executed.
}

The initialization part of the for loop can be a declaration statement or an expression statement, including the null statement. The initializations can include any sequence of expressions and declarations, separated by commas. Any object declared inside a for-init-statement has local scope, as if it had been declared immediately prior to the for statement. Although the name of the object can be used in more than one for loop in the same scope, the declaration can appear only once. For example:

#include <iostream.h>

void main()
{
    for( int i = 0; i < 100; ++i )
        cout << i << "\n";

    // The loop index, i, cannot be declared in the
    //  for-init-statement here because it is still in scope.
    for( i = 100; i >= 0; --i )
        cout << i << "\n";
}

Although the three fields of the for statement are normally used for initialization, testing for termination, and incrementing, they are not restricted to these uses. For example, the following code prints the numbers 1 to 100. The substatement is the null statement:

#include <iostream.h>

void main()
{
    for( int i = 0; i < 100; cout << ++i << endl )
        ;
}


Jump Statements

The C++ jump statements perform an immediate local transfer of control.

Syntax

jump-statement:

break ;
continue ;
return expressionopt ;
goto identifier ;


The C++ break Statement

The break statement is used to exit an iteration or switch statement. It transfers control to the statement immediately following the iteration substatement or switch statement.

The break statement terminates only the most tightly enclosing loop or switch statement. In loops, break is used to terminate before the termination criteria evaluate to 0. In the switch statement, break is used to terminate sections of code — normally before a case label. The following example illustrates the use of the break statement in a for loop:

for( ; ; )    // No termination condition.
{
    if( List->AtEnd() )
        break;

    List->Next();
}

cout << "Control transfers to here.\n";

Note There are other simple ways to escape a loop. It is best to use the break statement in more complex loops, where it can be difficult to tell whether the loop should be terminated before several statements have been executed.

For an example of using the break statement within the body of a switch statement, see The switch Statement.


The C++ continue Statement

The continue statement forces immediate transfer of control to the loop-continuation statement of the smallest enclosing loop. (The “loop-continuation” is the statement that contains the controlling expression for the loop.) Therefore, the continue statement can appear only in the dependent statement of an iteration statement (although it may be the sole statement in that statement). In a for loop, execution of a continue statement causes evaluation of expression2 and then expression3.

The following example shows how the continue statement can be used to bypass sections of code and skip to the next iteration of a loop:

#include <conio.h>

// Get a character that is a member of the zero-terminated
//  string, szLegalString. Return the index of the character
//  entered.
int GetLegalChar( char *szLegalString )
{
    char *pch;

    do
    {
        char ch = _getch();

        // Use strchr library function to determine if the
        //  character read is in the string. If not, use the
        //  continue statement to bypass the rest of the
        //  statements in the loop.
        if( (pch = strchr( szLegalString, ch )) == NULL )
            continue;

        // A character that was in the string szLegalString
        //  was entered. Return its index.
        return (pch - szLegalString);

        // The continue statement transfers control to here.
    } while( 1 );

    return 0;
}


The C++ return Statement

The return statement allows a function to immediately transfer control back to the calling function (or, in the case of the main function, transfer control back to the operating system). The return statement accepts an expression, which is the value passed back to the calling function. Functions of type void, constructors, and destructors cannot specify expressions in the return statement; functions of all other types must specify an expression in the return statement.

The expression, if specified, is converted to the type specified in the function declaration, as if an initialization were being performed. Conversion from the type of the expression to the return type of the function can cause temporary objects to be created. See Temporary Objects in Chapter 11 for more information about how and when temporaries are created.

When the flow of control exits the block enclosing the function definition, the result is the same as it would be if a return statement with no expression had been executed. This is illegal for functions that are declared as returning a value.

A function can have any number of return statements.


The goto Statement

The goto statement performs an unconditional transfer of control to the named label. The label must be in the current function.

For more information about labels and the goto statement, see Labeled Statements and Using Labels with the goto Statement.


Declaration Statements

Declaration statements introduce new names into the current scope. These names can be:

  • Type names (class, struct, union, enum, typedef, and pointer-to-member).

  • Object names.

  • Function names.

Syntax

declaration-statement:

declaration

If a declaration within a block introduces a name that is already declared outside the block, the previous declaration is hidden for the duration of the block. After termination of the block, the previous declaration is again visible.

Multiple declarations of the same name in the same block are illegal.

For more information about declarations and name hiding, see Declarations and Definitions and Scope in Chapter 2.


Declaration of Automatic Objects

In C++, objects can be declared with automatic storage class using the auto or register keyword. If no storage-class keyword is used for a local object (an object declared inside a function), auto is assumed. C++ initializes and declares these objects differently than objects declared with static storage classes.


Initialization of Automatic Objects

Each time declaration statements for objects of storage class auto or register are executed, initialization takes place. The following example, from The continue Statement, shows initialization of the automatic object ch inside the do loop.

#include <conio.h>

// Get a character that is a member of the zero-terminated
//  string, szLegalString. Return the index of the character
//  entered.
int GetLegalChar( char *szLegalString )
{
    char *pch;

    do
    {
        // This declaration statement is executed once for each
        //  execution of the loop.
        char ch = _getch();

        if( (pch = strchr( szLegalString, ch )) == NULL )
            continue;

        // A character that was in the string szLegalString
        //  was entered. Return its index.
        return (pch - szLegalString);
    } while( 1 );
}

For each iteration of the loop (each time the declaration is encountered), the macro _getch is evaluated and ch is initialized with the results. When control is transferred outside the block using the return statement, ch is destroyed (in this case, the storage is deallocated).

See Storage Classes in Chapter 2 for another example of initialization.


Destruction of Automatic Objects

Objects defined in a loop are destroyed once per iteration of the loop, on exit from the block, or when control transfers to a point prior to the declaration. Objects declared in a block that is not a loop are destroyed on exit from the block or when control transfers to a point prior to the declaration.

Note Destruction can mean simply deallocating the object or, for class-type objects, invoking the object’s destructor.

When a jump statement transfers control out of a loop or block, objects declared in the block transferred from are destroyed; objects in the block transferred to are not destroyed.

When control is transferred to a point prior to a declaration, the object is destroyed.


Transfers of Control

You can use the goto statement or a case label in a switch statement to specify a program that branches past an initializer. Such code is illegal unless the declaration that contains the initializer is in a block enclosed by the block in which the jump statement occurs.

The following example shows a loop that declares and initializes the objects total, ch, and i. There is also an erroneous goto statement that transfers control past an initializer.

// Read input until a nonnumeric character is entered.
while( 1 )
{
    int total = 0;

    char ch = _getch();

    if( ch >= '0' || ch <= '9' )
    {
        goto Label1;       // Error: transfers past initialization
                           //  of i.

        int i = ch - '0';
Label1:
        total += i;
    } // i would be destroyed here if the
      //  goto error were not present.
    else
        // Break statement transfers control out of loop,
        //  destroying total and ch.
        break;
}

In the preceding example, the goto statement tries to transfer control past the initialization of i. However, if i were declared but not initialized, the transfer would be legal.

The objects total and ch, declared in the block that serves as the statement of the while statement, are destroyed when that block is exited using the break statement.


Declaration of Static Objects

An object can be declared with static storage class using the static or extern keyword. Local objects must be explicitly declared as static or extern to have static storage class. All global objects (objects declared outside all functions) have static storage class. You cannot declare static instances in a tiny-model program.


Initialization of Static Objects

Global objects are initialized at program startup. (For more information about construction and destruction of global objects, see Additional Startup Considerations and Additional Termination Considerations in Chapter 2.)

Local objects declared as static are initialized the first time their declarations are encountered in the program flow. The following class, introduced in Chapter 2, Basic Concepts, shows how this works:

#include <iostream.h>
#include <string.h>

// Define a class that logs initializations and destructions.
class InitDemo
{
public:
   InitDemo( char *szWhat );
   ~InitDemo();
private:
   char *szObjName;
};

// Constructor for class InitDemo.
InitDemo::InitDemo( char *szWhat )
{
   if( szWhat != 0 && strlen( szWhat ) > 0 )
   {
      szObjName = new char[ strlen( szWhat ) + 1 ];
      strcpy( szObjName, szWhat );
   }
   else
      szObjName = 0;

   clog << "Initializing: " << szObjName << "\n";
}

// Destructor for InitDemo.
InitDemo::~InitDemo()
{
   if( szObjName != 0 )
   {
      clog << "Destroying: " << szObjName << "\n";
      delete szObjName;
   }
}

// Main function.
void main( int argc, char *argv[] )
{
    if( argc < 2 )
    {
        cerr << "Supply a one-letter argument.\n";
        return -1;
    }

    if( *argv[1] == 'a' )
    {
        cout << "*argv[1] was an 'a'\n";

        // Declare static local object.
        static InitDemo I1( "static I1" );
    }
    else
        cout << "*argv[1] was not an 'a'\n";
}

If the command-line argument supplied to this program starts with the lowercase letter “a,” the declaration of I1 is executed, the initialization takes place, and the result is:

*argv[1] was an 'a'
Initializing: static I1
Destroying: static I1

Otherwise, the flow of control bypasses the declaration of I1 and the result is:

*argv[1] was not an 'a'

When a static local object is declared with an initializer that does not evaluate to a constant expression, the object is given the value 0 (converted to the appropriate type) at the point before execution enters the block for the first time. However, the object is not visible and no constructors are called until the actual point of declaration.

At the point of declaration, the object’s constructor (if the object is of a class type) is called as expected. (Static local objects are only initialized the first time they are seen.)


Destruction of Static Objects

Local static objects are destroyed during termination specified by atexit.

If a static object was not constructed because the program’s flow of control bypassed its declaration, no attempt is made to destroy that object.


Exception Handling

Microsoft C++ supports two kinds of exception handling, C++ exception handling (try, throw, catch) and structured exception handling (__try/__except, __try/__finally). If possible, you should use C++ exception handling rather than structured exception handling.

Note In this section, the terms “structured exception handling” and “structured exception” (or “C exception”) refer exclusively to the structured exception handling mechanism provided by Win32®. All other references to exception handling (or “C++ exception”) refer to the C++ exception handling mechanism.

Although structured exception handling works with C and C++ source files, it is not specifically designed for C++. For C++ programs, you should use C++ exception handling.


The try, catch, and throw Statements

The C++ language provides built-in support for handling anomalous situations, known as “exceptions,” which may occur during the execution of your program. The try, throw, and catch statements have been added to the C++ language to implement exception handling. With C++ exception handling, your program can communicate unexpected events to a higher execution context that is better able to recover from such abnormal events. These exceptions are handled by code which is outside the normal flow of control. The Microsoft C++ compiler implements the C++ exception handling model based on the ISO WG21/ANSI X3J16 working papers towards the evolving standard for C++.

Syntax

try-block :

try compound-statement handler-list

handler-list :

handler handler-listopt

handler :

catch ( exception-declaration ) compound-statement

exception-declaration :

type-specifier-list declarator
type-specifier-list abstract-declarator
type-specifier-list
...

throw-expression :

throw assignment-expressionopt

The compound-statement after the try clause is the guarded section of code. The throw-expression “throws” (raises) an exception. The compound-statement after the catch clause is the exception handler, and “catches” (handles) the exception thrown by the throw-expression. The exception-declaration statement indicates the type of exception the clause handles. The type can be any valid data type, including a C++ class. If the exception-declaration statement is an ellipsis (...), the catch clause handles any type of exception, including a C exception. Such a handler must be the last handler for its try block.

The operand of throw is syntactically similar to the operand of a return statement.

Note Microsoft C++ does not support the function throw signature mechanism, as described in section 15.5 of the ANSI C++ draft. In addition, it does not support function-try-block described in section 15 of the ANSI C++ draft.

Execution proceeds as follows:

  1. Control reaches the try statement by normal sequential execution. The guarded section (within the try block) is executed.

  2. If no exception is thrown during execution of the guarded section, the catch clauses that follow the try block are not executed. Execution continues at the statement after the last catch clause following the try block in which the exception was thrown.

  3. If an exception is thrown during execution of the guarded section or in any routine the guarded section calls (either directly or indirectly), an exception object is created from the object created by the throw operand. (This implies that a copy constructor may be involved.) At this point, the compiler looks for a catch clause in a higher execution context that can handle an exception of the type thrown (or a catch handler that can handle any type of exception). The catch handlers are examined in order of their appearance following the try block. If no appropriate handler is found, the next dynamically enclosing try block is examined. This process continues until the outermost enclosing try block is examined.

  4. If a matching handler is still not found, or if an exception occurs while unwinding, but before the handler gets control, the predefined run-time function terminate is called. If an exception occurs after throwing the exception, but before the unwind begins, terminate is called.

  5. If a matching catch handler is found, and it catches by value, its formal parameter is initialized by copying the exception object. If it catches by reference, the parameter is initialized to refer to the exception object. After the formal parameter is initialized, the process of “unwinding the stack” begins. This involves the destruction of all automatic objects that were constructed (but not yet destructed) between the beginning of the try block associated with the catch handler and the exception’s throw site. Destruction occurs in reverse order of construction. The catch handler is executed and the program resumes execution following the last handler (that is, the first statement or construct which is not a catch handler). Control can only enter a catch handler through a thrown exception; never via a goto statement or a case label in a switch statement.

The following is a simple example of a try block and its associated catch handler. This example detects failure of a memory allocation operation using the new operator. If new is successful, the catch handler is never executed:

#include <iostream.h>

int main()
{
    char *buf;
    try
    {
        buf = new char[512];
        if( buf == 0 )
            throw "Memory allocation failure!";
    }
    catch( char * str )
    {
        cout << "Exception raised: " << str << '\n';
    }
    // ...
    return 0;
}

The operand of the throw expression specifies that an exception of type char * is being thrown. It is handled by a catch handler that expresses the ability to catch an exception of type char *. In the event of a memory allocation failure, this is the output from the preceding example:

Exception raised: Memory allocation failure!

The real power of C++ exception handling lies not only in its ability to deal with exceptions of varying types, but also in its ability to automatically call destructor functions during stack unwinding, for all local objects constructed before the exception was thrown.

The following example demonstrates C++ exception handling using classes with destructor semantics:

#include <iostream.h>

void MyFunc( void );

class CTest
{
public:
    CTest(){};
    ~CTest(){};
    const char *ShowReason() const { return "Exception in CTest class."; }

};

class CDtorDemo
{
public:
    CDtorDemo();
    ~CDtorDemo();
};

CDtorDemo::CDtorDemo()
{
    cout << "Constructing CDtorDemo.\n";
}

CDtorDemo::~CDtorDemo()
{
    cout << "Destructing CDtorDemo.\n";
}

void MyFunc()
{

    CDtorDemo D;
    cout<< "In MyFunc(). Throwing CTest exception.\n";
    throw CTest();
}

int main()
{
    cout << "In main.\n";
    try
    {
        cout << "In try block, calling MyFunc().\n";
        MyFunc();
    }
    catch( CTest E )
    {
        cout << "In catch handler.\n";
        cout << "Caught CTest exception type: ";
        cout << E.ShowReason() << "\n";
    }
    catch( char *str )
    {
        cout << "Caught some other exception: " << str << "\n";
    }
    cout << "Back in main. Execution resumes here.\n";
    return 0;
}

This is the output from the preceding example:

In main.
In try block, calling MyFunc().
Constructing CDtorDemo.
In MyFunc(). Throwing CTest exception.
Destructing CDtorDemo.
In catch handler.
Caught CTest exception type: Exception in CTest class.
Back in main. Execution resumes here.

Note that in this example, the exception parameter (the argument to the catch clause) is declared in both catch handlers:

catch( CTest E )
// ...
catch( char *str )
// ...

You do not need to declare this parameter; in many cases it may be sufficient to notify the handler that a particular type of exception has occurred. However, if you do not declare an exception object in the exception-declaration, you will not have access to that object in the catch handler clause.

A throw-expression with no operand re-throws the exception currently being handled. Such an expression should appear only in a catch handler or in a function called from within a catch handler. The re-thrown exception object is the original exception object (not a copy). For example:

try
{
    throw CSomeOtherException();
}
catch(...)       // Handle all exceptions
{
    // Respond (perhaps only partially) to exception
    // ...

    throw;       // Pass exception to some other handler
}


Unhandled C++ Exceptions

If a matching handler (or ellipsis catch handler) cannot be found for the current exception, the predefined terminate function is called. (You can also explicitly call terminate in any of your handlers.) The default action of terminate is to call abort. If you want terminate to call some other function in your program before exiting the application, call the set_terminate function with the name of the function to be called as its single argument. You can call set_terminate at any point in your program. The terminate routine always calls the last function given as an argument to set_terminate. For example:

#include <eh.h>    // For function prototypes
//...
void term_func() { // ... }
int main()
{
    try
    {
        // ...
        set_terminate( term_func );
        // ...
        throw "Out of memory!"; // No catch handler for this exception
    }
    catch( int )
    {
        cout << "Integer exception raised.";
    }
    return 0;
}

The term_func function should terminate the program or current thread, ideally by calling exit. If it doesn’t, and instead returns to its caller, abort is called.

For more information about C++ exception handling, see the C++ Annotated Reference Manual by Margaret Ellis and Bjarne Stroustrup.


Structured Exception Handling

The __try/__except and __try/__finally statements are a Microsoft extension to the C language that enables applications to gain control of a program after events that would normally terminate execution.

Note Structured exception handling works with C and C++ source files. However, it is not specifically designed for C++. Although destructors for local objects will be called if you use structured exception handling in a C++ program (if you use the /GX compiler option), you can ensure that your code is more portable by using C++ exception handling. The C++ exception handling mechanism is more flexible, in that it can handle exceptions of any type.

For more information, see The try-except Statement and The try-finally Statement in the C Language Reference.

Syntax

try-except-statement :

__try compound-statement
__except ( expression ) compound-statement

try-finally-statement :

__try compound-statement
__finally compound-statement

If you have C modules that use structured exception handling, they can be mixed with C++ modules that use C++ exception handling. When a C (structured) exception is raised, it can be handled by the C handler, or it can be caught by a C++ catch handler, whichever is dynamically closest to the exception context. One of the major differences between the two models is that when a C exception is raised, it is always of type unsigned int, whereas a C++ exception can be of any type. That is, C exceptions are identified by an unsigned integer value, whereas C++ exceptions are identified by data type. However, while a C++ catch handler can catch a C exception (for example, via an “ellipsis” catch handler), a C exception can also be handled as a typed exception by using a C exception wrapper class. By deriving from this class, each C exception can be attributed a specific derived class.

To use a C exception wrapper class, you install a custom C exception translator function which is called by the internal exception handling mechanism each time a C exception is thrown. Within your translator function, you can throw any typed exception, which can be caught by an appropriate matching C++ catch handler. To specify a custom translation function, call the _set_se_translator function with the name of your translation function as its single argument.


Declarations

Declarations introduce new names into a program. Topics covered in this chapter include the following uses for declarations:

  • Specify storage class, type, and linkage for an object.

  • Specify storage class, type, and linkage for a function.

  • Define a function.

  • Provide an initial value for an object.

  • Associate a name with a constant (enumerated type declaration).

  • Declare a new type (class, struct, or union declaration).

  • Specify a synonym for a type (typedef declaration).

  • Specify a family of classes or functions (template declaration).

  • Specify a namespace.

In addition to introducing a new name, a declaration specifies how an identifier is to be interpreted by the compiler. Declarations do not automatically reserve storage associated with the identifier — reserving storage is done by definitions.

Note Most declarations are also definitions.

Syntax

declaration:

decl-specifiersopt declarator-listopt ;
function-definition
linkage-specification
template-specification

The declarators in declarator-list contain the names being declared. Although the declarator-list is shown as optional, it can be omitted only in declarations or definitions of a function.

Note The declaration of a function is often called a “prototype.” This declaration provides type information about arguments and the function’s return type that allows the compiler to perform correct conversions and to ensure type safety.

The decl-specifiers part of a declaration is also shown as optional; however, it can be omitted only in declarations of class types or enumerations.

Declarations occur in a scope. This controls the visibility of the name declared and the duration of the object defined (if any). For more information about how scope rules interact with declarations, see Scope in Chapter 2.

An object declaration is also a definition unless it contains the extern storage-class specifier described in Storage-Class Specifiers. A function declaration is also a definition unless it is a prototype — a function header with no defining function body. An object’s definition causes allocation of storage and appropriate initializations for that object.


Specifiers

This section explains the decl-specifiers portion of declarations. (The syntax for declarations is given at the beginning of this chapter.)

Syntax

decl-specifiers :

decl-specifiersopt decl-specifier

decl-specifier :

storage-class-specifier
type-specifier
fct-specifier
friend
typedef
__declspec ( extended-decl-modifier-seq )

The Microsoft-specific keyword, __declspec, is discussed in Extended Attribute Syntax in Appendix B.

The decl-specifiers portion of a declaration is the longest sequence of decl-specifiers that can be construed to be a type name. The remainder of the declaration is the name or names introduced. The examples in the following list illustrates this concept:

Declaration decl-specifiers name
char *lpszAppName;

char *

lpszAppName

typedef char * LPSTR;

char *

LPSTR

LPSTR strcpy( LPSTR, LPSTR );

LPSTR

strcpy

volatile void *pvvObj;

volatile void *

pvvObj

Because signed, unsigned, long, and short all imply int, a typedef name following one of these keywords is taken to be a member of declarator-list, not of decl-specifiers.

Note Because a name can be redeclared, its interpretation is subject to the most recent declaration in the current scope. Redeclaration can affect how names are interpreted by the compiler, particularly typedef names.


Storage-Class Specifiers

The C++ storage-class specifiers tell the compiler the duration and visibility of the object or function they declare, as well as where an object should be stored.

Syntax

storage-class-specifier:

auto
register
static
extern


Automatic Storage-Class Specifiers

The auto and register storage-class specifiers can be used only to declare names used in blocks or to declare formal arguments to functions. The term “auto” comes from the fact that storage for these objects is automatically allocated at run time (normally on the program’s stack).


The auto Keyword

Few programmers use the auto keyword in declarations because all block-scoped objects not explicitly declared with another storage class are implicitly automatic. Therefore, the following two declarations are equivalent:

{
auto int i;    // Explicitly declared as auto.
int      j;    // Implicitly auto.
}


The register Keyword

Microsoft Specific

The compiler does not accept user requests for register variables; instead, it makes its own register choices when global register-allocation optimization (/Oe option) is on. However, all other semantics associated with the register keyword are honored.

END Microsoft Specific

ANSI C does not allow for taking the address of a register object; this restriction does not apply to C++. However, if the address-of operator (&) is used on an object, the compiler must put the object in a location for which an address can be represented — in practice, this means in memory instead of in a register.


Static Storage-Class Specifiers

The static storage-class specifiers, static and extern, can be applied to objects and functions. Table 6.1 shows where the keywords static and extern can and cannot be used.

Table 6.1 Use of static and extern

Construct | Can static be Used? | Can extern be Used?
Function declarations within a block | No | Yes
Formal arguments to a function | No | No
Objects in a block | Yes | Yes
Objects outside a block | Yes | Yes
Functions | Yes | Yes
Class member functions | Yes | No
Class member data | Yes | No
typedef names | No | No

A name specified using the static keyword has internal linkage except for the static members of a class that have external linkage. That is, it is not visible outside the current translation unit. A name specified using the extern keyword has external linkage unless previously defined as having internal linkage. For more information about the visibility of names, see Scope and Program and Linkage in Chapter 2.

Note Functions that are declared as inline and that are not class member functions are given the same linkage characteristics as functions declared as static.

A class name whose declaration has not yet been encountered by the compiler can be used in an extern declaration. The name introduced with such a declaration cannot be used until the class declaration has been encountered.


Names Without Storage-Class Specifiers

File-scope names with no explicit storage-class specifiers have external linkage unless they are:

  • Declared using the const keyword.

  • Previously declared with internal linkage.


Function Specifiers

You can use the inline and virtual keywords as specifiers in function declarations. This use of virtual differs from its use in the base-class specifier of a class definition.


inline Specifier

The inline specifier instructs the compiler to replace function calls with the code of the function body. This substitution is “inline expansion” (sometimes called “inlining”). Inline expansion alleviates the function-call overhead at the potential cost of larger code size.

The inline keyword tells the compiler that inline expansion is preferred. However, the compiler can create a separate instance of the function (instantiate) and create standard calling linkages instead of inserting the code inline. Two cases where this can happen are:

  • Recursive functions.

  • Functions that are referred to through a pointer elsewhere in the translation unit.

Note that for a function to be considered as a candidate for inlining, it must use the new-style function definition. Functions that are declared as inline and that are not class member functions have internal linkage unless otherwise specified.

Microsoft Specific

The __inline keyword is equivalent to inline.

The __forceinline keyword instructs the compiler to inline the function without performing any cost/benefit analysis. The programmer must exercise good judgement in using this keyword. Indiscriminate use of __forceinline can result in larger, and sometimes even slower, code.

Even with __forceinline, the compiler cannot inline code in all circumstances. The compiler cannot inline a function if:

  • The function or its caller is compiled with /Ob0 (the default option for debug builds).

  • The function and the caller use different types of exception handling (C++ exception handling in one, structured exception handling in the other).

  • The function has a variable argument list.

  • The function uses inline assembly, unless compiled with /Og, /Ox, /O1, or /O2.

  • The function returns an unwindable object by value, when compiled with /GX, /EHs, or /EHa.

  • The function receives a copy-constructed object passed by value, when compiled with /-GX, /EHs, or /EHa.

  • The function is recursive and not accompanied by #pragma(inline_recursion, on). With the inline_recursion pragma, recursive functions can be inlined to a depth of eight calls, or as determined by the inline_depth pragma (see below).

  • The function is virtual.

  • The program takes the address of the function.

If the compiler cannot inline a function declared with __forceinline, it generates a level 1 warning (4714).

END Microsoft Specific

As with normal functions, there is no defined order of evaluation of the arguments to an inline function. In fact, it could be different from the order in which the arguments are evaluated when passed using normal function call protocol.

Microsoft Specific

Recursive functions can be substituted inline to a depth specified by the inline_depth pragma. After that depth, recursive function calls are treated as calls to an instance of the function. The inline_recursion pragma controls the inline expansion of a function currently under expansion. See the Inline-Function Expansion (/Ob) compiler option for related information.

END Microsoft Specific


Inline Class Member Functions

A function defined in the body of a class declaration is an inline function. Consider the following class declaration:

class Account
{
public:
    Account(double initial_balance) { balance = initial_balance; }
    double GetBalance();
    double Deposit( double Amount );
    double Withdraw( double Amount );
private:
    double balance;
};

The Account constructor is an inline function. The member functions GetBalance, Deposit, and Withdraw are not specified as inline but can be implemented as inline functions using code such as the following:

inline double Account::GetBalance()
{
    return balance;
}

inline double Account::Deposit( double Amount )
{
    return ( balance += Amount );
}

inline double Account::Withdraw( double Amount )
{
    return ( balance -= Amount );
}

Note In the class declaration, the functions were declared without the inline keyword. The inline keyword can be specified in the class declaration; the result is the same.

A given inline member function must be declared the same way in every compilation unit. This constraint causes inline functions to behave as if they were instantiated functions. Additionally, there must be exactly one definition of an inline function.

A class member function defaults to external linkage unless a definition for that function contains the inline specifier. The preceding example shows that these functions need not be explicitly declared with the inline specifier; using inline in the function definition causes it to be an inline function. However, it is illegal to redeclare a function as inline after a call to that function.


Inline Functions versus Macros

Although inline functions are similar to macros (because the function code is expanded at the point of the call at compile time), inline functions are parsed by the compiler, whereas macros are expanded by the preprocessor. As a result, there are several important differences:

  • Inline functions follow all the protocols of type safety enforced on normal functions.

  • Inline functions are specified using the same syntax as any other function except that they include the inline keyword in the function declaration.

  • Expressions passed as arguments to inline functions are evaluated once. In some cases, expressions passed as arguments to macros can be evaluated more than once. The following example shows a macro that converts lowercase letters to uppercase:
    #include <stdio.h>
#include <conio.h>

#define toupper(a) ((a) >= 'a' && ((a) <= 'z') ? ((a)-('a'-'A')):(a))

void main()
{
    char ch = toupper( _getch() );
    printf( “%c”, ch );
}

    The intent of the expression toupper( _getch() ) is that a character should be read from the console device (stdin) and, if necessary, converted to uppercase.

    Because of the implementation, _getch is executed once to determine whether the character is greater than or equal to “a,” and once to determine whether it is less than or equal to “z.” If it is in that range, _getch is executed again to convert the character to uppercase. This means the program waits for two or three characters when, ideally, it should wait for only one.

    Inline functions remedy this problem:

    #include <stdio.h>
#include <conio.h>

inline char toupper( char a )
{
    return ((a >= 'a' && a <= 'z') ? a-('a'-'A') : a );
}

void main()
{
    char ch = toupper( _getch() );
    printf( "%c", ch );
}


When to Use Inline Functions

Inline functions are best used for small functions such as accessing private data members. The main purpose of these one- or two-line “accessor” functions is to return state information about objects; short functions are sensitive to the overhead of function calls. Longer functions spend proportionately less time in the calling/returning sequence and benefit less from inlining.

The Point class, introduced in Function-Call Results in Chapter 4 can be optimized as follows:

class Point
{
public:
    // Define "accessor" functions as
    //  reference types.
    unsigned& x();
    unsigned& y();
private:
    unsigned _x;
    unsigned _y;
};

inline unsigned& Point::x()
{
    return _x;
}
inline unsigned& Point::y()
{
    return _y;
}

Assuming coordinate manipulation is a relatively common operation in a client of such a class, specifying the two accessor functions (x and y in the preceding example) as inline typically saves the overhead on:

  • Function calls (including parameter passing and placing the object’s address on the stack)

  • Preservation of caller’s stack frame

  • New stack-frame setup

  • Return-value communication

  • Old stack-frame restore

  • Return


virtual Specifier

The virtual keyword can be applied only to nonstatic class member functions. It signifies that binding of calls to the function is deferred until run time. For more information, see Virtual Functions in Chapter 9.


typedef Specifier

The typedef specifier defines a name that can be used as a synonym for a type or derived type. You cannot use the typedef specifier inside a function definition.

Syntax

typedef-name:

identifier

A typedef declaration introduces a name that, within its scope, becomes a synonym for the type given by the decl-specifiers portion of the declaration. In contrast to the class, struct, union, and enum declarations, typedef declarations do not introduce new types — they introduce new names for existing types.

One use of typedef declarations is to make declarations more uniform and compact. For example:

typedef char CHAR;          // Character type.
typedef CHAR * PSTR;        // Pointer to a string (char *).
...
PSTR strchr( PSTR source, CHAR target );

The names introduced by the preceding declarations are synonyms for:

Name Synonymous Type
CHAR
 char
PSTR
 char *

The preceding example code declares a type name, CHAR, which is then used to define the derived type name PSTR (a pointer to a string). Finally, the names are used in declaring the function strchr. To see how the typedef keyword can be used to clarify declarations, contrast the preceding declaration of strchr with the following declaration:

char * strchr( char * source, char target );

To use typedef to specify fundamental and derived types in the same declaration, you can separate declarators with commas. For example:

typedef char CHAR, *PSTR;

A particularly complicated use of typedef is to define a synonym for a “pointer to a function that returns type T.” For example, a typedef declaration that means “pointer to a function that takes no arguments and returns type void” uses this code:

typedef void (*PVFN)();

The synonym can be handy in declaring arrays of functions that are to be invoked through a pointer:

#include <iostream.h>
#include <stdlib.h>

extern void func1();         // Declare 4 functions.
extern void func2();         // These functions are assumed to be
extern void func3();         //  defined elsewhere.
extern void func4();
                             // Declare synonym for pointer to
typedef void (*PVFN)();      //  function that takes no arguments
                             //  and returns type void.

void main( int argc, char * argv[] )
{
    // Declare an array of pointers to functions.
    PVFN pvfn1[] = { func1, func2, func3, func4 };

    // Invoke the function specified on the command line.
    if( argc > 0 && *argv[1] > '0' && *argv[1] <= '4' )
   (*pvfn1[atoi( argv[1] ) - 1])();
}


Redeclaration of typedef Names

The typedef declaration can be used to redeclare the same name to refer to the same type. For example:

// FILE1.H
typedef char CHAR;

// FILE2.H
typedef char CHAR;

// PROG.CPP
#include "file1.h"
#include "file2.h"   // OK
...

The program PROG.CPP includes two header files, both of which contain typedef declarations for the name CHAR. As long as both declarations refer to the same type, such redeclaration is acceptable.

A typedef cannot redefine a name that was previously declared as a different type. Therefore, if FILE2.H contains

// FILE2.H
typedef int CHAR;     // Error

the compiler issues an error because of the attempt to redeclare the name CHAR to refer to a different type. This extends to constructs such as:

typedef char CHAR;
typedef CHAR CHAR;      // OK: redeclared as same type

typedef union REGS      // OK: name REGS redeclared
{                       //  by typedef name with the
    struct wordregs x;  //  same meaning.
    struct byteregs h;
} REGS;


Use of typedef with Class Types

Use of the typedef specifier with class types is supported largely because of the ANSI C practice of declaring unnamed structures in typedef declarations. For example, many C programmers use the following:

typedef struct    // Declare an unnamed structure and give it the
{                 //  typedef name POINT.
    unsigned x;
    unsigned y;
} POINT;

The advantage of such a declaration is that it enables declarations like:

POINT ptOrigin;

instead of:

struct point_t ptOrigin;

In C++, the difference between typedef names and real types (declared with the class, struct, union, and enum keywords) is more distinct. Although the C practice of declaring a nameless structure in a typedef statement still works, it provides no notational benefits as it does in C.

In the following code, the POINT function is not a type constructor. It is interpreted as a function declarator with an int return type.

typedef struct
{
    POINT();         // Not a constructor.
    unsigned x;
    unsigned y;
} POINT;

The preceding example declares a class named POINT using the unnamed class typedef syntax. POINT is treated as a class name; however, the following restrictions apply to names introduced this way:

  • The name (the synonym) cannot appear after a class, struct, or union prefix.

  • The name cannot be used as constructor or destructor names within a class declaration.

In summary, this syntax does not provide any mechanism for inheritance, construction, or destruction.


Name Space of typedef Names

Names declared using typedef occupy the same name space as other identifiers (except statement labels). Therefore, they cannot use the same identifier as a previously declared name, except in a class-type declaration. Consider the following example:

typedef unsigned long UL;   // Declare a typedef name, UL.
int UL;                     // Error: redefined.

The name-hiding rules that pertain to other identifiers also govern the visibility of names declared using typedef. Therefore, the following example is legal in C++:

typedef unsigned long UL;   // Declare a typedef name, UL.
...
long Beep
{
    unsigned int UL;        // Redeclaration hides typedef name.
    ...
}
// typedef name "unhidden" here.


friend Specifier

The friend specifier is used to designate functions or classes that have the same access privileges as class member functions. Friend functions and classes are covered in detail in Friends in Chapter 10.


C++ Type Specifiers

Type specifiers determine the type of the name being declared.

Syntax

type-specifier:

simple-type-name
class-specifier
enum-specifier
elaborated-type-specifier
:: class-name
const
volatile

The following sections discuss simple type names, elaborated type specifiers, and nested type names.


Simple Type Names

A simple type name is the name of a complete type.

Syntax

simple-type-name:

complete-class-name
qualified-type-name
char
short
int
long
signed
unsigned
float
double
void

Table 6.2 shows how the simple type names can be used together.

Table 6.2 Type Name Combinations

Type | Can Appear With | Comments
int | long or short, but not both | Type int implies type long int.
long | int or double | Type long implies type long int.
short | int | Type short implies type short int.
signed | char, short, int, or long | Type signed implies signed int. The most-significant bit of objects of type signed char and bit fields of signed integral types is taken to be the sign bit.
unsigned | char, short, int, or long | Type unsigned implies unsigned int. The most-significant bit of objects of type unsigned char and bit fields of unsigned integral types is not treated as the sign bit.


Elaborated Type Specifiers

Elaborated type specifiers are used to declare user-defined types. These can be either class- or enumerated-types.

Syntax

elaborated-type-specifier :

class-key class-name
class-key identifier
enum enum-name

class-key :

class
struct
union

If identifier is specified, it is taken to be a class name. For example:

class Window;

This statement declares the Window identifier as a class name. This syntax is used for forward declaration of classes. For more information about class names, see Class Names in Chapter 8.

If a name is declared using the union keyword, it must also be defined using the union keyword. Names that are defined using the class keyword can be declared using the struct keyword (and vice versa). Therefore, the following code samples are legal:

// Legal example 1
struct A;    // Forward declaration of A.

class A      // Define A.
{
public:
    int i;
};

// Legal example 2
class A;     // Forward declaration of A.

struct A     // Define A.
{
private:
    int i;
};

// Legal example 3
union A;      // Forward declaration of A.

union A       // Define A.
{
    int  i;
    char ch[2];
};

These examples, however, are illegal:

// Illegal example 1
union A;      // Forward declaration of A.

struct A      // Define A.
{
    int i;
};
// Illegal example 2
union A;      // Forward declaration of A.

class A       // Define A.
{
public:
    int i;
};
// Illegal example 3
struct A;     // Forward declaration of A.

union A       // Define A.
{
    int  i;
    char ch[2];
};


Nested Type Names

Microsoft C++ supports declaration of nested types — both named and anonymous.

Syntax

qualified-type-name :

typedef-name
class-name :: qualified-type-name

complete-class-name :

qualified-class-name
:: qualified-class-name

qualified-class-name :

class-name
class-name :: qualified-class-name

In some programming situations, it makes sense to define nested types. These types are visible only to member functions of the class type in which they are defined. They can also be made visible by constructing a qualified type name using the scope-resolution operator (::).

Note One commonly used class hierarchy that employs nested types is iostream. In the iostream header files, the definition of class ios includes a series of enumerated types, which are packaged for use only with the iostream library.

The following example defines nested classes:

class WinSystem
{
public:
    class Window
    {
    public:
        Window();         // Default constructor.
        ~Window();        // Destructor.
        int NumberOf();   // Number of objects of class.
        int Count();      // Count number of objects of class.
    private:
        static int CCount;
    };
    class CommPort
    {
    public:
        CommPort();       // Default constructor.
        ~CommPort();      // Destructor.
        int NumberOf();   // Number of objects of class.
        int Count();      // Count number of objects of class.
    private:
        static int CCount;
    };
};

// Initialize WinSystem static members.
int WinSystem::Window::CCount = 0;
int WinSystem::CommPort::CCount = 0;

To access a name defined in a nested class, use the scope-resolution operator (::) to construct a complete class name. Use of this operator is shown in the initializations of the static members in the preceding example. To use a nested class in your program, use code such as:

WinSystem::Window Desktop;
WinSystem::Window AppWindow;

cout << "Number of active windows: " << Desktop.Count() << "\n";

Nested anonymous classes or structures can be defined as:

class Ledger
{
    class
    {
    public:
        double   PayableAmt;
        unsigned PayableDays;
    } Payables;

    class
    {
    public:
        double   RecvableAmt;
        unsigned RecvableDays;
    } Receivables;
};

An anonymous class must be an aggregate that has no member functions and no static members.

Note Although an enumerated type can be defined inside a class declaration, the reverse is not true; class types cannot be defined inside enumeration declarations.


C++ Enumeration Declarations

An enumeration is a distinct integral type that defines named constants. Enumerations are declared using the enum keyword.

Syntax

enum-name :

identifier

enum-specifier :

enum identifieropt { enum-listopt }

enum-list :

enumerator
enum-list , enumerator

enumerator :

identifier
identifier = constant-expression

Enumerated types are valuable when an object can assume a known and reasonably limited set of values. Consider the example of the suits from a deck of cards:

class Card
{
public:
    enum Suit
    {
        Diamonds,
        Hearts,
        Clubs,
        Spades
    };
    // Declare two constructors: a default constructor,
    //  and a constructor that sets the cardinal and
    //  suit value of the new card.
    Card();
    Card( int CardInit, Suit SuitInit );

    // Get and Set functions.
    int   GetCardinal();          // Get cardinal value of card.
    int   SetCardinal();          // Set cardinal value of card.
    Suit  GetSuit();              // Get suit of card.
    void  SetSuit(Suit new_suit);  // Set suit of card.
    char *NameOf();               // Get string representation of card.
private:
    Suit  suit;
    int   cardinalValue;
};

// Define a postfix increment operator for Suit.
inline Card::Suit operator++( Card::Suit &rs, int )
{
    return rs = (Card::Suit)(rs + 1);
}

The preceding example defines a class, Card, that contains a nested enumerated type, Suit. To create a pack of cards in a program, use code such as:

Card *Deck[52];
int   j = 0;

for( Card::Suit curSuit = Card::Diamonds; curSuit <= Card::Spades;
     curSuit++ )
    for( int i = 1; i <= 13; ++i )
        Deck[j++] = new Card( i, curSuit );

In the preceding example, the type Suit is nested; therefore, the class name (Card) must be used explicitly in public references. In member functions, however, the class name can be omitted.

In the first segment of code, the postfix increment operator for Card::Suit is defined. Without a user-defined increment operator, curSuit could not be incremented. For more information about user-defined operators, see Overloaded Operators in Chapter 12.

Consider the code for the NameOf member function (a better implementation is presented later):

char* Card::NameOf() // Get the name of a card.
{
    static char szName[20];
    static char *Numbers[] =
    { "1", "2", "3", "4", "5", "6", "7", "8", "9",
      "10", "Jack", "Queen", "King"
    };
    static char *Suits[] =
    { "Diamonds", "Hearts", "Clubs", "Spades" };

    if( GetCardinal() < 13)
        strcpy( szName, Numbers[GetCardinal()] );

    strcat( szName, " of " );

    switch( GetSuit() )
    {
    // Diamonds, Hearts, Clubs, and Spades do not need explicit
    //  class qualifier.
    case Diamonds: strcat( szName, "Diamonds" ); break;
    case Hearts:   strcat( szName, "Hearts" );   break;
    case Clubs:    strcat( szName, "Clubs" );    break;
    case Spades:   strcat( szName, "Spades" );   break;
    }

    return szName;
}

An enumerated type is an integral type. The identifiers introduced with the enum declaration can be used wherever constants appear. Normally, the first identifier’s value is 0 (Diamonds, in the preceding example), and the values increase by one for each succeeding identifier. Therefore, the value of Spades is 3.

Any enumerator in the list, including the first one, can be initialized to a value other than its default value. Suppose the declaration of Suit had been the following:

enum Suit
{
    Diamonds = 5,
    Hearts,
    Clubs = 4,
    Spades
};

Then the values of Diamonds, Hearts, Clubs, and Spades would have been 5, 6, 4, and 5, respectively. Note that 5 is used more than once.

The default values for these enumerators simplify implementation of the NameOf function:

char* Card::NameOf() // Get the name of a card.
{
    static char szName[20];
    static char *Numbers[] =
    { "1", "2", "3", "4", "5", "6", "7", "8", "9",
      "10", "Jack", "Queen", "King"
    };
    static char *Suits[] =
    { "Diamonds", "Hearts", "Clubs", "Spades"};

    if( GetCardinal() < 13)
        strcpy( szName, Numbers[GetCardinal()] );

    strcat( szName, " of " );

    strcat( szName, Suits[GetSuit()] );

    return szName;
}

The accessor function GetSuit returns type Suit, an enumerated type. Because enumerated types are integral types, they can be used as arguments to the array subscript operator. (For more information, see Subscript Operator in Chapter 4.)


Enumerator Names

The names of enumerators must be different from any other enumerator or variable in the same scope. However, the values can be duplicated.


Definition of Enumerator Constants

Enumerators are considered defined immediately after their initializers; therefore, they can be used to initialize succeeding enumerators. The following example defines an enumerated type that ensures that any two enumerators can be combined with the OR operator:

enum FileOpenFlags
{
    OpenReadOnly  = 1,
    OpenReadWrite = OpenReadOnly  << 1,
    OpenBinary    = OpenReadWrite << 1,
    OpenText      = OpenBinary    << 1,
    OpenShareable = OpenText      << 1
};

In this example, the preceding enumerator initializes each succeeding enumerator.


Conversions and Enumerated Types

Because enumerated types are integral types, any enumerator can be converted to another integral type by integral promotion. Consider this example:

enum Days
{
    Sunday,
    Monday,
    Tuesday,
    Wednesday,
    Thursday,
    Friday,
    Saturday
};

int  i;
Days d = Thursday;

i = d;    // Converted by integral promotion.
cout << "i = " << i << "\n";

However, there is no implicit conversion from any integral type to an enumerated type. Therefore (continuing with the preceding example), the following statement is in error:

d = 6;    // Erroneous attempt to set d to Saturday.

Assignments such as this, where no implicit conversion exists, must use a cast to perform the conversion:

d = (Days)6;    // Explicit cast-style conversion to type Days.
d = Days( 4 );  // Explicit function-style conversion to type Days.

The preceding example shows conversions of values that coincide with the enumerators. There is no mechanism that protects you from converting a value that does not coincide with one of the enumerators. For example:

d = Days( 967 );

Some such conversions may work. However, there is no guarantee that the resultant value will be one of the enumerators. Additionally, if the size of the enumerator is too small to hold the value being converted, the value stored may not be what you expect.


Linkage Specifications

The term “linkage specification” refers to the protocol for linking functions (or procedures) written in different languages. The following calling conventions are affected:

  • Case sensitivity of names.

  • Decoration of names. In C, the compiler prefixes names with an underscore. This is often called “decoration.” In C++, name decoration is used to retain type information through the linkage phase. (See Decorated Names, in Visual C++ Programmer’s Guide.)

  • Order in which arguments are expected on the stack.

  • Responsibility for adjusting the stack on function return. Either the called function or the calling function is responsible.

  • Passing of hidden arguments (whether any hidden arguments are passed).

Syntax

linkage-specification :

extern string-literal { declaration-listopt }
extern string-literal declaration

declaration-list :

declaration
declaration-list

Linkage specification facilitates gradually porting C code to C++ by allowing the use of existing code.

Microsoft Specific

The only linkage specifications currently supported by Microsoft C++ are "C" and "C++".

END Microsoft Specific

The following example declares the functions atoi and atol with C linkage:

extern "C"
{
    int  atoi( char *string );
    long atol( char *string );
}

Calls to these functions are made using C linkage. The same result could be achieved with these two declarations:

extern "C" int  atoi( char *string );
extern "C" long atol( char *string );

Microsoft Specific

All Microsoft C standard include files use conditional compilation directives to detect C++ compilation. When a C++ compilation is detected, the prototypes are enclosed in an extern "C" directive as follows:

// Sample.h
#if defined(__cplusplus)
extern "C"
{
#endif

// Function declarations

#if defined(__cplusplus)
}
#endif

END Microsoft Specific

You do not need to declare the functions in the standard include files as extern "C".

If a function is overloaded, no more than one of the functions of the same name can have a linkage specifier. (For more information, see Function Overloading in Chapter 7.)

Table 6.3 shows how various linkage specifications work.

Table 6.3 Effects of Linkage Specifications

Specification | Effect
On an object | Affects linkage of that object only
On a function | Affects linkage of that function and all functions or objects declared within it
On a class | Affects linkage of all nonmember functions and objects declared within the class

If a function has more than one linkage specification, they must agree; it is an error to declare functions as having both C and C++ linkage. Furthermore, if two declarations for a function occur in a program — one with a linkage specification and one without — the declaration with the linkage specification must be first. Any redundant declarations of functions that already have linkage specification are given the linkage specified in the first declaration. For example:

extern "C" int CFunc1();
...
int CFunc1();            // Redeclaration is benign; C linkage is
                         //  retained.

int CFunc2();
...
extern "C" int CFunc2(); // Error: not the first declaration of
                         //  CFunc2;  cannot contain linkage
                         //  specifier.

Functions and objects explicitly declared as static within the body of a compound linkage specifier ({ }) are treated as static functions or objects; the linkage specifier is ignored. Other functions and objects behave as if declared using the extern keyword. (See Storage-Class Specifiers for details about the extern keyword.)


Template Specifications

The template declaration specifies a set of parameterized classes or functions.

Note For more information, see Template Topics in Visual C++ Programmer’s Guides.

Syntax

template-declaration :

template < template-argument-list > declaration

template-argument-list :

template-argument
template-argument-list , template-argument

template-argument :

type-argument
argument-declaration

type-argument :

class identifier
typename identifier

The declaration declares a function or a class. With function templates, each template-argument must appear at least once in the template-argument-list of the function being declared.

The template-argument-list is a list of arguments used by the template function that specifies which parts of the following code will vary. For example:

template< class T, int i > class MyStack...

In this case the template can receive a type (class T) and a constant parameter (int I). The template will use type T and the constant integer i upon construction. Within the body of the MyStack declaration, you must refer to the T identifier.

The typename keyword can be used in the template-argument-list. The following template declarations are identical:

template< class T1, class T2 > class X...
template< typename T1, typename T2 > class X...

Template arguments of the following form are allowed:

template<typename Type> class allocator {};
template<typename Type,
   typename Allocator = allocator<Type> > class stack {
};
stack<int> MyStack;

Visual C++ supports the reuse of template parameters in the template parameter list. For example, the following code is now legal:

class Y {...};
template<class T, T* pT> class X1 {...};
template<class T1, class T2 = T1> class X2 {...};

Y aY;

X1<Y, &aY> x1;
X2<int> x2;

A template declaration itself does not generate code; it specifies a family of classes or functions, one or more of which will be generated when referenced by other code.

Template declarations have global or namespace scope.

Visual C++ performs syntax checking of template definitions. This version of Visual C++ can detect errors that previous versions cannot. The compiler can now detect syntax errors of templates that are defined but never instantiated.

Here is a list of common errors which could compile with the Visual C++ 4.0 compiler, but not the Visual C++ 5.0 or later compiler:

  • A user-defined type is used in a template declaration before it is declared, but it is declared before the first instantiation or use of the template. For example:

    template<class T> class X {
    //...
    Data m_data;//Error Visual C++ 5.0 or later, Data not defined
    };

    class Data {...};

    void g() { X<int> x1; }

    Move the declaration of Data before the class template X to fix this problem.

  • A member function is declared outside a class template, whereas it is never declared inside the class. For example:

    template<class T> class X {
    //no mf declared here
    };

    //This definition did not cause an error with Visual
    //C++ 4.0, but it will cause an error with Visual
    //C++ 5.0 or later
    //
    template<class T> void X<T>::mf() {...};

  • A class identifier is considered to be a normal class unless declared to be a class template. For example, the following code generates an error with Visual C++ 5.0 or later but not with Visual C++ 4.0:

    template<class T> class X {
    friend class Y<T>;//Parsed as Y ‘less-than’
    //T ‘greater-than’;
    Z<T> mf( );//Parsed as Z ‘less-than’ T
    //‘greater-than’;
    };

    template<class T> class Y {...};
    template<class T> class Z {...};

    X<int> x;

    To fix the problem, forward declare Y and Z before the definition of X.

    template<class T> class Y {...};
    template<class T> class Z {...};

    template<class T> class X {...};


Referencing a Template

To reference a template class or function use the following syntax:

Syntax

template-class-name :

template-name < template-arg-list >

template-arg-list :

template-arg
template-arg-list , template-arg

template-arg :

expression
type-name

All template-arg arguments must be constant expressions. The compiler creates a new instance (called an instantiation) of the templated class or function if there is no exact match to a previously generated template. For example:

MyStack< unsigned long, 5 > stack1;     // creates a stack of
                                        // unsigned longs
MyStack< DWORD, 5 >   stack2;    // uses code created above
MyStack< char, 6 > stack3;    // generates new code
MyStack< MyClass, 6 > stack4;   // generates stack of MyClass objects

Each generated template function creates its own static variables and members.


Function Templates

Class templates define a family of related classes that are based on the parameters passed to the class upon instantiation. Function templates are similar to class templates, but define a family of functions. Here is a function template that swaps two items:

template< class T > void MySwap( T& a, T& b )
{
   T c;
   c = a; a = b; b = c;
}

Although this function could be performed by a nontemplated function, using void pointers, the template version is type-safe. Consider the following calls:

int j = 10;
int k = 18;
CString Hello = "Hello, Windows!";
MySwap( j, k );          //OK
MySwap( j, Hello );      //error

The second MySwap call triggers a compile-time error, since the compile cannot generate a MySwap function with parameters of different types. If void pointers were used, both function calls would compile correctly, but the function would not work properly at run time.

Explicit specification of the template arguments for a function template is allowed. For example:

template<class T> void f(T) {...}
void g(char j) {
   f<int>(j);   //generate the specialization f(int)
}

When the template argument is explicitly specified, normal implicit conversions are done to convert the function argument to the type of the corresponding function template parameters. In the above example, the compiler will convert (char j) to type int.


Member Function Templates

After declaring a templated class, define member functions as function templates. For example:

template<class T, int i> class MyStack
{
    T*  pStack;
    T StackBuffer[i];
    int cItems = i * sizeof(T);
public:
    MyStack( void );
    void push( const T item );
    T& pop( void );
};

template< class T, int i > MyStack< T, i >::MyStack( void )
{ ... } ;
template< class T, int i > void MyStack< T, i >::push( const T item )
{ ... } ;
template< class T, int i > T& MyStack< T, i >::pop( void )
{ ... } ;

Note that the definition of the constructor function does not include the template argument list twice.


Explicit Instantiation

Explicit instantiation lets you create an instantiation of a templated class or function without actually using it in your code. Since this is useful when you are creating library (.LIB) files that use templates for distribution, uninstantiated template definitions are not put into object (.OBJ) files.

The following explicitly instantiates MyStack for int variables and six items:

template class MyStack<int, 6>;

This statement creates an instantiation of MyStack without reserving any storage for an object; code is generated for all members.

The following explicitly instantiates only the constructor member function:

template MyStack<int, 6>::MyStack( void );

Visual C++ 6.0 supports explicit instantiation of function templates. Versions prior to 5.0 supported the explicit instantiation of class templates only. For example, the following code is now legal:

template<class T> void f(T) {...}

//Instantiate f with the explicitly specified template
//argument ‘int’
//
template void f<int> (int);

//Instantiate f with the deduced template argument ‘char’
//
template void f(char);

Microsoft Specific

You can use the extern keyword to prevent the automatic instantiation of members. For example:

extern template class MyStack<int, 6>;

Similarly, you can mark specific members as being external and not instantiated as follows:

extern template MyStack<int, 6>::MyStack( void );

Note The extern keyword in the specialization only applies to member functions defined outside of the body of the class. Functions defined inside the class declaration are considered inline functions and are always instantiated.

END Microsoft Specific


Differences from Other Implementations

Microsoft Specific

Templates are not officially standardized and, as a result, different C++ compiler vendors have implemented them differently. The following list shows some differences between this version of Visual C++ and other compilers. Note that this list will change in future versions of the compiler.

  • The compiler cannot instantiate a template outside of the module in which it is defined.

  • Templates cannot be used with functions declared with __declspec (dllimport) or __declspec (dllexport).

  • All template arguments must be of an unambiguous type that exactly matches that of the template parameter list. For example:
    template< class T > T check( T );
template< class S > void watch( int (*)(S) );
watch( check );     //error

    The compiler should instantiate the check templated function in the form int check( int ), but the inference can not be followed.

  • Friend functions must be declared before they are used in a templated class. You cannot have a friend function defined within a class definition. This is because the friend function could be a templated function, which would cause an illegal nested template definition.

END Microsoft Specific


Namespaces

The C++ language provides a single global namespace. This can cause problems with global name clashes. For instance, consider these two C++ header files:

// one.h
char func(char);
class String { ... };

// somelib.h
class String { ... };

With these definitions, it is impossible to use both header files in a single program; the String classes will clash.

A namespace is a declarative region that attaches an additional identifier to any names declared inside it. The additional identifier makes it less likely that a name will conflict with names declared elsewhere in the program. It is possible to use the same name in separate namespaces without conflict even if the names appear in the same translation unit. As long as they appear in separate namespaces, each name will be unique because of the addition of the namespace identifier. For example:

// one.h
namespace one
{
    char func(char);
    class String { ... };
}

// somelib.h
namespace SomeLib
{
    class String { ... };
}

Now the class names will not clash because they become one::String and SomeLib::String, respectively.

Declarations in the file scope of a translation unit, outside all namespaces, are still members of the global namespace.


namespace Declaration

A namespace declaration identifies and assigns a name to a declarative region.

Syntax

original-namespace-name :

identifier

namespace-definition :

original-namespace-definition
extension-namespace-definition
unnamed-namespace-definition

original-namespace-definition :

namespace identifier { namespace-body }

extension-namespace-definition :

namespace original-namespace-name { namespace-body }

unnamed-namespace-definition :

namespace { namespace-body }

namespace-body :

declaration-seqopt

The identifier in an original-namespace-definition must be unique in the declarative region in which it is used. The identifier is the name of the namespace and is used to reference its members. Subsequently, in that declarative region, it is treated as an original-namespace-name.

The declarative region of a namespace-definition is its namespace-body.

A namespace can contain data and function declarations. The declaration-seq is a list of these declarations which are said to be members of the namespace.


Unnamed namespaces

An unnamed-namespace-definition behaves as if it were replaced by:

namespace unique { namespace-body }
using namespace unique;

Each unnamed namespace has an identifier, represented by unique, that differs from all other identifiers in the entire program. For example:

namespace { int i; }          // unique::i
void f() { i++; }             // unique::i++

namespace A {
    namespace {
        int I;      // A::unique::i
        int j;      // A::unique::j
    }
}

using namespace A;

void h()
{
    I++;            //error: unique::i or A::unique::i
    A::i++;         // error: A::i undefined
    j++;            // A::unique::j++
}

Unnamed namespaces are a superior replacement for the static declaration of variables. They allow variables and functions to be visible within an entire translation unit, yet not visible externally. Although entities in an unnamed namespace might have external linkage, they are effectively qualified by a name unique to their translation unit and therefore can never be seen from any other translation unit.


namespace Definition

A namespace-definition can be nested within another namespace-definition. Every namespace-definition must appear either at file scope or immediately within another namespace-definition.

For example:

namespace A {
    int j = 3;
    int f(int k);
}

namespace Outer {
    int n = 6;
    int func(int num);

    namespace Inner {
        float f = 9.993;
    }
}

void main()
{
    namespace local { ... }        // error: not at global scope
    .
    .
    .
}

Unlike other declarative regions, the definition of a namespace can be split over several parts of a single translation unit.

namespace A {
    // declare namespace A variables
    int i;
    int j;
}

namespace B {
    ...
}
    .
    .
    .
namespace A {
    // declare namespace A functions
    void func(void);
    int int_func(int i);
}

When a namespace is continued in this manner, after its initial definition, the continuation is called an extension-namespace-definition.


Defining namespace Members

Members of a namespace may be defined within that namespace. For example:

namespace X { void f() { } }

Members of a named namespace can be defined outside the namespace in which they are declared by explicit qualification of the name being defined. However, the entity being defined must already be declared in the namespace. In addition, the definition must appear after the point of declaration in a namespace that encloses the declaration’s namespace. For example:

namespace Q {
    namespace V {
        void f();
    }

    void V::f() { }        // ok
    void V::g() { }        // error, g() is not yet a member of V

    namespace V {
        void g();
    }
}


Namespace Alias

A namespace-alias is an alternative name for a namespace.

Syntax

namespace-alias :

identifier

namespace-alias-definition :

namespace identifier = qualified-namespace-specifier;

qualified-namespace-specifier :

::opt nested-name-specifieropt class-or-namespace-name

A namespace-alias-definition declares an alternate name for a namespace. The identifier is a synonym for the qualified-namespace-specifier and becomes a namespace-alias. For example:

namespace a_very_long_namespace_name { ... }
namespace AVLNN = a_very_long_namespace_name;
// AVLNN is now a namespace-alias for a_very_long_namespace_name.

A namespace-name cannot be identical to any other entity in the same declarative region. In addition, a global namespace-name cannot be the same as any other global entity name in a given program.


using Declaration

The using declaration introduces a name into the declarative region in which the using declaration appears. The name becomes a synonym for an entity declared elsewhere. It allows an individual name from a specific namespace to be used without explicit qualification. This is in contrast to the using directive, which allows all the names in a namespace to be used without qualification. See using Directive for more information.

Syntax

using-declaration :

using ::opt nested-name-specifier unqualified-id
using :: unqualified-id

A using-declaration can be used in a class definition. For example:

class B
{
    void f(char);
    void g(char);
};

class D : B
{
    using B::f;
    void f(int) { f('c'); }        // calls B::f(char)
    void g(int) { g('c'); }        // recursively calls D::g(int)
                                   // only B::f is being used
};

When used to declare a member, a using-declaration must refer to a member of a base class. For example:

class C
{
    int g();
};

class D2 : public B
{
    using B::f;          // ok: B is a base of D2
    using C::g;          // error: C isn't a base of D2
};

Members declared with a using-declaration can be referenced using explicit qualification. The :: prefix refers to the global namespace. For example:

void f();

namespace A
{
    void g();
}

namespace X
{
    using ::f;        // global f
    using A::g;       // A's g
}

void h()
{
    X::f();           // calls ::f
    X::g();           // calls A::g
}

Just as with any declaration, a using-declaration can be used repeatedly only where multiple declarations are allowed. For example:

namespace A
{
    int i;
}

void f()
{
    using A::i;
    using A::i;        // ok: double declaration
}

class B
{
protected:
    int i;
};

class X : public B
{
public:
    using B::i;
    using B::i;        // error: class members cannot be multiply declared
};

When a using-declaration is made, the synonym created by the declaration refers only to definitions that are valid at the point of the using-declaration. Definitions added to a namespace after the using-declaration are not valid synonyms. For example:

namespace A
{
    void f(int);
}

using A::f;        // f is a synonym for A::f(int) only

namespace A
{
    void f(char);
}

void f()
{
    f('a');            // refers to A::f(int), even though A::f(char) exists
}

void b()
{
    using A::f;        // refers to A::f(int) AND A::f(char)
    f('a');            // calls A::f(char);
}

A name defined by a using-declaration is an alias for its original name. It does not affect the type, linkage or other attributes of the original declaration.

If a set of local declarations and using-declarations for a single name are given in a declarative region, they must all refer to the same entity, or they must all refer to functions. For example:

namespace B
{
    int i;
    void f(int);
    void f(double);
}

void g()
{
    int i;
    using B::i;          // error: i declared twice
    void f(char);
    using B::f;          // ok: each f is a function
}

In the example above, the using B::i statement causes a second int i to be declared in the g() function. The using B::f statement does not conflict with the f(char) function because the function names introduced by B::f have different parameter types.

A local function declaration cannot have the same name and type as a function introduced by a using-declaration. For example:

namespace B
{
    void f(int);
    void f(double);
}

namespace C
{
    void f(int);
    void f(double);
    void f(char);
}

void h()
{
    using B::f;          // introduces B::f(int) and B::f(double)
    using C::f;          // C::f(int), C::f(double), and C::f(char)
    f('h');              // calls C::f(char)
    f(1);                // error: ambiguous: B::f(int) or C::f(int)?
    void f(int);         // error: conflicts with B::f(int) and C::f(int)
}

When a using-declaration introduces a name from a base class into a derived class scope, member functions in the derived class override virtual member functions with the same name and argument types in the base class. For example:

struct B
{
    virtual void f(int);
    virtual void f(char);
    void g(int);
    void h(int);
};

struct D : B
{
     using B::f;
    void f(int);         // ok: D::f(int) overrides B::f(int)

    using B::g;
    void g(char);        // ok: there is no B::g(char)

    using B::h;
    void h(int);         // error: D::h(int) conflicts with B::h(int)
                         // B::h(int) is not virtual
};

void f(D* pd)
{
    pd->f(1);            // calls D::f(int)
    pd->f('a');          // calls B::f(char)
    pd->g(1);            // calls B::g(int)
    pd->g('a');          // calls D::g(char)
}

All instances of a name mentioned in a using-declaration must be accessible. In particular, if a derived class uses a using-declaration to access a member of a base class, the member name must be accessible. If the name is that of an overloaded member function, then all functions named must be accessible. For example:

class A
{
private:
    void f(char);
public:
    void f(int);
protected:
    void g();
};

class B : public A
{
    using A::f;          // error: A::f(char) is inaccessible
public:
    using A::g;          // B::g is a public synonym for A::g
};

See Chapter 10, Member-Access Control for more information on accessibility of members.


using Directive

The using-directive allows the names in a namespace to be used without the namespace-name as an explicit qualifier. In contrast to a using declaration, which allows an individual name to be used without qualification, the using directive allows all the names in a namespace to be used without qualification. See using Declaration for more information.

Syntax

using-directive :

using namespace ::opt nested-name-specifieropt namespace-name

The intent of the using-directive is to allow unique, descriptive names to be used when declaring functions and variables, without requiring the complete name every time access to the functions or variables is needed. Of course, the complete, qualified name can still be used to retain clarity.

The unqualified names can be used from the point of the using directive on. If a namespace is extended after a using-directive is given, the additional members of the namespace can be used, without qualification, after the extended-namespace-definition. For example:

namespace M
{
    int i;
}

using namespace M;

namespace N
{
    int j;
    double f() { return M::d; }        // error: M::d does not yet exist
}

namespace M        // namespace extension
{
    double d;
}
                   // now M::d can be used

It is possible for a using-directive to introduce conflicting names when used in another namespace. For example:

namespace M
{
    int i;
}

namespace N
{
    int i;
    using namespace M;    // no error here
}
    .
    .
    .
void f()
{
    using namespace N;
    i = 7;                // error: ambiguous: M::i or N::i?
}

In this example, bringing M::i into namespace N does not hide the declaration of N::i, but instead creates an ambiguity when N::i is used. In this manner, the using-directive can easily introduce unintended ambiguities. Consider the following code fragment:

namespace D
{
    int d1;
    void f(int);
    void f(char);
}

using namespace D;

int d1;             // no conflict with D::d1

namespace E
{
    int e;
    void f(int);
}

namespace D         // namespace extension
{
    int d2;
    using namespace E;
    void f(int);
}

void f()
{
    d1++;           // error: ambiguous: ::d1 or D::d1?
    ::d1++;         // ok
    D::d1++;        // ok
    d2++;           // ok: D::d2
    e++;            // ok: E::e
    f(1);           // error: ambiguous: D::f(int) or E::f(int)?
    f('a');         // ok D::f(char)
}

When a variable is referenced after a using-directive, the local variable of the same name takes precedence over the one declared in the specified namespace. For example:

namespace N {
   int data = 4;
}

void f(bool flag) {
   int data = 0;

   if (flag) {
      using namespace N;

      prinf(“data=%d\n”, data);
   }
}

void main() {
   f(true);
}

In the above code, the variable data referenced in the printf statement is the local variable initialized to 0, instead of the variable initialized in namespace N. The output is data=0 instead of data=4.

In the presence of namespace using-directives, the way qualified names are looked up is shown in the following example:

namespace A {
   int flag = 0;
}

namespace B {
   using namespace A;
}

namespace C {
   using namespace A;
   using namespace B;
}

void main() {
   printf(“C::flag = %d\n”, C::flag);
}

The qualified name (C::flag) is resolved to (A::flag) due to the namespace using-directives in namespace C.


Explicit Qualification

A name in a class or namespace can be accessed using an explicit qualifier.

Syntax

id-expression :

unqualified-id
qualified-id

nested-name-specifier :

class-or-namespace-name
:: nested-name-specifieropt

class-or-namespace-name :

class-name
namespace-name

namespace-name :

original-namespace-name
namespace-alias

This is very similar to using the scope operator to resolve access to a member of a class. For more information, see Qualified Names in Chapter 4.


Declarators

A “declarator” is the part of a declaration that names an object, type, or function. Declarators appear in a declaration as one or more names separated by commas; each name can have an associated initializer.

Syntax

declarator-list:

init-declarator
declarator-list , init-declarator

init-declarator:

declarator initializeropt

This chapter includes the following topics:

  • Overview

  • Type names

  • Abstract declarators

  • Function definitions

  • Initializers


Overview of Declarators

Declarators are the components of a declaration that specify names. Declarators can also modify basic type information to cause names to be functions or pointers to objects or functions. (Specifiers, discussed in Chapter 6, Declarations, convey properties such as type and storage class. Modifiers, discussed in this chapter and in Appendix B, Microsoft-Specific Modifiers, modify declarators.) Figure 7.1 shows a complete declaration of two names, szBuf and strcpy, and calls out the components of the declaration.

Figure 7.1 Specifiers, Modifiers, and Declarators

Microsoft Specific

Most Microsoft extended keywords can be used as modifiers to form derived types; they are not specifiers or declarators. (See Appendix B, Microsoft-Specific Modifiers.)

END Microsoft Specific

Syntax

declarator :

dname
ptr-operator declarator
declarator ( argument-declaration-list ) cv-mod-list
declarator [ constant-expressionopt ]
( declarator )

ptr-operator :

* cv-qualifier-listopt
& cv-qualifier-listopt
complete-class-name :: * cv-qualifier-listopt

cv-qualifier-list :

cv-qualifier cv-qualifier-listopt

cv-qualifier :

const
volatile

cv-mod-list :

cv-qualifier cv-mod-listopt
pmodel cv-mod-listopt

dname :

name
class-name
~ class-name
typedef-name
qualified-type-name

Declarators appear in the declaration syntax after an optional list of specifiers (decl-specifiers). These specifiers are discussed in Chapter 6, Declarations. A declaration can contain more than one declarator, but each declarator declares only one name. The following sample declaration shows how specifiers and declarators are combined to form a complete declaration:

const char *pch, ch;

In this preceding declaration, the keywords const and char make up the list of specifiers. Two declarators are listed: *pch and ch. The simplified syntax of a declaration, then, is the following, where const char is the type and *pch and ch are the declarators:

type declarator1[, declarator2[...,declaratorn] ] ;

When the binding of elements in a declarator list does not yield the desired result, you can use parentheses for clarification. A better technique, however, is to use a typedef or a combination of parentheses and the typedef keyword. Consider declaring an array of pointers to functions. Each function must obey the same protocol so that the arguments and return values are known:

//  Function returning type int that takes one
//   argument of type char *.
typedef int (*PIFN)( char * );

//  Declare an array of 7 pointers to functions
//   returning int and taking one argument of type
//   char *.
PIFN pifnDispatchArray[7];

The equivalent declaration can be written without the typedef declaration, but it is so complicated that the potential for error exceeds any benefits:

int ( *pifnDispatchArray[7] )( char * );


Type Names

Type names are used in some declarators in the following ways:

  • In explicit conversions

  • As arguments to the sizeof operator

  • As arguments to the new operator

  • In function prototypes

  • In typedef statements

A type name consists of type specifiers, as described in Chapter 6, Declarations, and Abstract Declarators.

In the following example, the arguments to the function strcpy are supplied using their type names. In the case of the source argument, const char is the specifier and * is the abstract declarator:

static char *szBuf, *strcpy( char *dest, const char *source );

Syntax

type-name :

type-specifier-list abstract-declaratoropt

type-specifier-list :

type-specifier type-specifier-listopt

abstract-declarator :

ptr-operator abstract-declaratoropt
abstract-declaratoropt ( argument-declaration-list ) cv-qualifier-listopt
abstract-declaratoropt [ constant-expressionopt ]
( abstract-declarator )


C++ Abstract Declarators

An abstract declarator is a declarator in which the identifier is omitted. (For related information, see Type Names.)

The following abstract declarators are discussed in this section:

  • Pointers

  • References

  • Pointers to members

  • Arrays

  • Functions

  • Default arguments

An abstract declarator is a declarator that does not declare a name — the identifier is left out. For example,

char *

declares the type “pointer to type char.” This abstract declarator can be used in a function prototype as follows:

char *strcmp( char *, char * );

In this prototype (declaration), the function’s arguments are specified as abstract declarators. The following is a more complicated abstract declarator that declares the type “pointer to a function that takes two arguments, both of type char *,” and returns type char *:

char * (*)( char *, char * )

Since abstract declarators completely declare a type, it is legal to form expressions of the form:

// Get the size of array of 10 pointers to type char.
size_t nSize = sizeof( char *[10] );

// Allocate a pointer to a function that has no
//  return value and takes no arguments.
typedef void (PVFN *)();
PVFN *pvfn = new PVFN;

// Allocate an array of pointers to functions that
//  return type WinStatus, and take one argument of
//  type WinHandle.
typedef WinStatus (PWSWHFN *)( WinHandle );
PWSWHFN pwswhfnArray[] = new PWSWHFN[10];


Ambiguity Resolution

To perform explicit conversions from one type to another, you must use casts, specifying the desired type name. Some type casts result in syntactic ambiguity. The following function-style type cast is ambiguous:

char *aName( String( s ) );

It is unclear whether it is a function declaration or an object declaration with a function-style cast as the initializer: It could declare a function returning type char * that takes one argument of type String, or it could declare the object aName and initialize it with the value of s cast to type String.

If a declaration can be considered a valid function declaration, it is treated as such. Only if it cannot possibly be a function declaration — that is, if it would be syntactically incorrect — is a statement examined to see if it is a function-style type cast. Therefore, the compiler considers the statement to be a declaration of a function and ignores the parentheses around the identifier s. On the other hand, the statements:

char *aName( (String)s );

and

char *aName = String( s );

are clearly declarations of objects, and a user-defined conversion from type String to type char * is invoked to perform the initialization of aName.


Pointers

Pointers are declared using the declarator syntax:

* cv-qualifier-listopt dname

A pointer holds the address of an object. The full declaration, then, is:

decl-specifiers * cv-qualifier-listopt dname ;

A simple example of such a declaration is:

char *pch;

The preceding declaration specifies that pch points to an object of type char.


const and volatile Pointers

The const and volatile keywords change how pointers are treated. The const keyword specifies that the pointer cannot be modified after initialization; the pointer is protected from modification thereafter.

The volatile keyword specifies that the value associated with the name that follows can be modified by actions other than those in the user application. Therefore, the volatile keyword is useful for declaring objects in shared memory that can be accessed by multiple processes or global data areas used for communication with interrupt service routines.

When a name is declared as volatile, the compiler reloads the value from memory each time it is accessed by the program. This dramatically reduces the possible optimizations. However, when the state of an object can change unexpectedly, it is the only way to ensure predictable program performance.

To declare the object pointed to by the pointer as const or volatile, use a declaration of the form:

const    char *cpch;
volatile char *vpch;

To declare the value of the pointer — that is, the actual address stored in the pointer — as const or volatile, use a declaration of the form:

char * const    pchc;
char * volatile pchv;

The C++ language prevents assignments that would allow modification of an object or pointer declared as const. Such assignments would remove the information that the object or pointer was declared with, thereby violating the intent of the original declaration. Consider the following declarations:

const char cch = 'A';
char        ch = 'B';

Given the preceding declarations of two objects (cch, of type const char, and ch, of type char), the following declaration/initializations are valid:

const char        *pch1 = &cch;
const char *const  pch4 = &cch;
const char        *pch5 = &ch;
char              *pch6 = &ch;
char       *const  pch7 = &ch;
const char *const  pch8 = &ch;

The following declaration/initializations are erroneous.

char *pch2 = &cch;        // Error
char *const pch3 = &cch;  // Error

The declaration of pch2 declares a pointer through which a constant object might be modified and is therefore disallowed. The declaration of pch3 specifies that the pointer is constant, not the object; the declaration is disallowed for the same reason the pch2 declaration is disallowed.

The following eight assignments show assigning through pointer and changing of pointer value for the preceding declarations; for now, assume that the initialization was correct for pch1 through pch8.

*pch1 = 'A';  // Error: object declared const
pch1 = &ch;   // OK: pointer not declared const
*pch2 = 'A';  // OK: normal pointer
pch2 = &ch;   // OK: normal pointer
*pch3 = 'A';  // OK: object not declared const
pch3 = &ch;   // Error: pointer declared const
*pch4 = 'A';  // Error: object declared const
pch4 = &ch;   // Error: pointer declared const

Pointers declared as volatile or as a mixture of const and volatile obey the same rules.

Pointers to const objects are often used in function declarations as follows:

char *strcpy( char *szTarget, const char *szSource );

The preceding statement declares a function, strcpy, that takes two arguments of type “pointer to char” and returns a pointer to type char. Because the arguments are passed by reference and not by value, the function would be free to modify both szTarget and szSource if szSource were not declared as const. The declaration of szSource as const assures the caller that szSource cannot be changed by the called function.

Note Because there is a standard conversion from typename * to const typename *, it is legal to pass an argument of type char * to strcpy. However, the reverse is not true; no implicit conversion exists to remove the const attribute from an object or pointer.

A const pointer of a given type can be assigned to a pointer of the same type. However, a pointer that is not const cannot be assigned to a const pointer. The following code shows correct and incorrect assignments:

int *const cpObject = 0;
int *pObject;

void main()
{
    pObject = cpObject; // OK
    cpObject = pObject; // Error
}


References

References are declared using the declarator syntax:

Syntax

& cv-qualifier-listopt dname

A reference holds the address of an object but behaves syntactically like an object. A reference declaration consists of an (optional) list of specifiers followed by a reference declarator.

Syntax

decl-specifiers & cv-qualifier-listopt dname ;

Consider the user-defined type Date:

struct Date
{
    short DayOfWeek;
    short Month;
    short Day;
    short Year;
};

The following statements declare an object of type Date and a reference to that object:

Date  Today;             // Declare the object.
Date& TodayRef = Today;  // Declare the reference.

The name of the object, Today, and the reference to the object, TodayRef, can be used identically in programs:

Today.DayOfWeek = 3;   // Tuesday
TodayRef.Month  = 7;   // July


Reference-Type Function Arguments

It is often more efficient to pass references, rather than functions, to large objects. This allows the compiler to pass the address of the object while maintaining the syntax that would have been used to access the object. Consider the following example that uses the Date structure:

// Create a Julian date of the form DDDYYYY
// from a Gregorian date.
long JulianFromGregorian( Date& GDate )
{
    static int cDaysInMonth[] = {
    31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
    };
    long JDate;

    // Add in days for months already elapsed.
    for( int i = 0; i < GDate.Month - 1; ++i )
        JDate += cDaysInMonth[i];

    // Add in days for this month.
    JDate += GDate.Day;

    // Check for leap year.
    if( GDate.Year % 100 != 0 && GDate.Year % 4 == 0 )
        JDate++;

    // Add in year.
    JDate *= 10000;
    JDate += GDate.Year;

    return JDate;
}

The preceding code shows that members of a structure passed by reference are accessed using the member-selection operator (.) instead of the pointer member-selection operator (–>).

Although arguments passed as reference types observe the syntax of nonpointer types, they retain one important characteristic of pointer types: they are modifiable unless declared as const. Because the intent of the preceding code is not to modify the object GDate, a more appropriate function prototype is:

long JulianFromGregorian( const Date& GDate );

This prototype guarantees that the function JulianFromGregorian will not change its argument.

Any function prototyped as taking a reference type can accept an object of the same type in its place because there is a standard conversion from typename to typename&.


Reference-Type Function Returns

Functions can be declared to return a reference type. There are two reasons to make such a declaration:

  • The information being returned is a large enough object that returning a reference is more efficient than returning a copy.

  • The type of the function must be an l-value.

Just as it can be more efficient to pass large objects to functions by reference, it also can be more efficient to return large objects from functions by reference. Reference-return protocol eliminates the necessity of copying the object to a temporary location prior to returning.

Reference-return types can also be useful when the function must evaluate to an l-value. Most overloaded operators fall into this category, particularly the assignment operator. Overloaded operators are covered in Overloaded Operators in Chapter 12. Consider the Point example from Chapter 4:

class Point
{
public:
    // Define "accessor" functions as
    //  reference types.
    unsigned& x();
    unsigned& y();
private:
    unsigned obj_x;
    unsigned obj_y;
};

unsigned& Point :: x()
{
    return obj_x;
}
unsigned& Point :: y()
{
    return obj_y;
}

void main()
{
    Point ThePoint;

    // Use x() and y() as l-values.
    ThePoint.x() = 7;
    ThePoint.y() = 9;

    // Use x() and y() as r-values.
    cout << "x = " << ThePoint.x() << "\n"
         << "y = " << ThePoint.y() << "\n";
}

Notice that the functions x and y are declared as returning reference types. These functions can be used on either side of an assignment statement.

Declarations of reference types must contain initializers except in the following cases:

  • Explicit extern declaration

  • Declaration of a class member

  • Declaration within a class

  • Declaration of an argument to a function or the return type for a function


References to Pointers

References to pointers can be declared in much the same way as references to objects. Declaring a reference to a pointer yields a modifiable value that is used like a normal pointer. The following code samples illustrate the difference between using a pointer to a pointer and a reference to a pointer:

#include <iostream.h>
#include <string.h>

// Define a binary tree structure.
struct BTree
{
    char  *szText;
    BTree *Left;
    BTree *Right;
};
// Define a pointer to the root of the tree.
BTree *btRoot = 0;

int Add1( BTree **Root, char *szToAdd );
int Add2( BTree*& Root, char *szToAdd );
void PrintTree( BTree* btRoot );

int main( int argc, char *argv[] )
{
    if( argc < 2 )
    {
        cerr << "Usage: Refptr [1 | 2]" << "\n";
        cerr << "\n\twhere:\n";
        cerr << "\t1 uses double indirection\n";
        cerr << "\t2 uses a reference to a pointer.\n";
        cerr << "\n\tInput is from stdin.\n";
        return 1;
    }

    char *szBuf = new char[132];

    // Read a text file from the standard input device and
    //  build a binary tree.
    while( !cin.eof() )
    {
        cin.get( szBuf, 132, '\n' );
        cin.get();
        if( strlen( szBuf ) )
            switch( *argv[1] )
            {
            // Method 1: Use double indirection.
            case '1':
                Add1( &btRoot, szBuf );
                break;
            // Method 2: Use reference to a pointer.
            case '2':
                Add2( btRoot, szBuf );
                break;
            default:
                cerr << "Illegal value '" << *argv[1]
                     << "' supplied for add method.\n"
                     << "Choose 1 or 2.\n";
                return -1;
            }
    }

    // Display the sorted list.
    PrintTree( btRoot );
    return 0;
}

// PrintTree: Display the binary tree in order.
void PrintTree( BTree* btRoot )
{
    // Traverse the left branch of the tree recursively.
    if( btRoot->Left )
        PrintTree( btRoot->Left );

    // Print the current node.
    cout << btRoot->szText << "\n";

    // Traverse the right branch of the tree recursively.
    if( btRoot->Right )
        PrintTree( btRoot->Right );
}

// Add1: Add a node to the binary tree.
//       Uses double indirection.
int Add1( BTree **Root, char *szToAdd )
{
    if( (*Root) == 0 )
    {
        (*Root) = new BTree;
        (*Root)->Left = 0;
        (*Root)->Right = 0;
        (*Root)->szText = new char[strlen( szToAdd ) + 1];
        strcpy( (*Root)->szText, szToAdd );
        return 1;
    }
    else if( strcmp( (*Root)->szText, szToAdd ) > 0 )
        return Add1( &((*Root)->Left), szToAdd );
    else
        return Add1( &((*Root)->Right), szToAdd );
}

// Add2: Add a node to the binary tree.
//       Uses reference to pointer
int Add2( BTree*& Root, char *szToAdd )
{
    if( Root == 0 )
    {
        Root = new BTree;
        Root->Left = 0;
        Root->Right = 0;
        Root->szText = new char[strlen( szToAdd ) + 1];
        strcpy( Root->szText, szToAdd );
        return 1;
    }
    else if( strcmp( Root->szText, szToAdd ) > 0 )
        return Add2( Root->Left, szToAdd );
    else
        return Add2( Root->Right, szToAdd );
}

In the preceding program, functions Add1 and Add2 are functionally equivalent (although they are not called the same way). The difference is that Add1 uses double indirection whereas Add2 uses the convenience of a reference to a pointer.


Pointers to Members

Declarations of pointers to members are special cases of pointer declarations.

Syntax

decl-specifiers class-name :: * cv-qualifier-listopt dname ;

A pointer to a member of a class differs from a normal pointer because it has type information for the type of the member and for the class to which the member belongs. A normal pointer identifies (has the address of) only a single object in memory. A pointer to a member of a class identifies that member in any instance of the class. The following example declares a class, Window, and some pointers to member data.

class Window
{
public:
    Window();                               // Default constructor.
    Window( int x1, int y1,                 // Constructor specifying
        int x2, int y2 );                   //  window size.
    BOOL SetCaption( const char *szTitle ); // Set window caption.
    const char *GetCaption();               // Get window caption.
    char *szWinCaption;                     // Window caption.
};

// Declare a pointer to the data member szWinCaption.
char * Window::* pwCaption = &Window::szWinCaption;

In the preceding example, pwCaption is a pointer to any member of class Window that has type char*. The type of pwCaption is char * Window::*. The next code fragment declares pointers to the SetCaption and GetCaption member functions.

const char * (Window::*pfnwGC)() = &Window::GetCaption;
BOOL (Window::*pfnwSC)( const char * ) = &Window::SetCaption;

The pointers pfnwGC and pfnwSC point to GetCaption and SetCaption of the Window class, respectively. The code copies information to the window caption directly using the pointer to member pwCaption:

Window wMainWindow;
Window *pwChildWindow = new Window;
char   *szUntitled    = "Untitled -  ";
int    cUntitledLen   = strlen( szUntitled );

strcpy( wMainWindow.*pwCaption, szUntitled );
(wMainWindow.*pwCaption)[cUntitledLen - 1] = '1';     //same as
//wMainWindow.SzWinCaption [ ] = '1';
strcpy( pwChildWindow->*pwCaption, szUntitled );
(pwChildWindow->*pwCaption)[szUntitledLen - 1] = '2'; //same as
//pwChildWindow->szWinCaption[ ] = '2';

The difference between the .* and –>* operators (the pointer-to-member operators) is that the .* operator selects members given an object or object reference, while the –>* operator selects members through a pointer. (For more about these operators, see Expressions with Pointer-to-Member Operators in Chapter 4.)

The result of the pointer-to-member operators is the type of the member — in this case, char *.

The following code fragment invokes the member functions GetCaption and SetCaption using pointers to members:

// Allocate a buffer.
char szCaptionBase[100];

// Copy the main window caption into the buffer
//  and append " [View 1]".
strcpy( szCaptionBase, (wMainWindow.*pfnwGC)() );
strcat( szCaptionBase, " [View 1]" );

// Set the child window's caption.
(pwChildWindow->*pfnwSC)( szCaptionBase );


Restrictions on Pointers to Members

The address of a static member is not a pointer to member. It is a regular pointer to the one instance of the static member. Because only one instance of a static member exists for all objects of a given class, the ordinary address-of (&) and dereference (*) operators can be used.


Pointers to Members and Virtual Functions

Invoking a virtual function through a pointer-to-member function works as if the function had been called directly: the correct function is looked up in the v-table and invoked. The following code shows how this is done:

class Base
{
public:
    virtual void Print();
};
void (Base ::* bfnPrint)() = &Base :: Print;

void Base :: Print()
{
    cout << "Print function for class 'Base'\n";
}

class Derived : public Base
{
public:
    void Print();  // Print is still a virtual function.
};

void Derived :: Print()
{
    cout << "Print function for class 'Derived'\n";
}

void main()
{
    Base   *bPtr;
    Base    bObject;
    Derived dObject;

    bPtr = &bObject;    // Set pointer to address of bObject.
    (bPtr->*bfnPrint)();

    bPtr = &dObject;    // Set pointer to address of dObject.
    (bPtr->*bfnPrint)();
}

The output from this program is:

Print function for class 'Base'
Print function for class 'Derived'

The key to virtual functions working, as always, is invoking them through a pointer to a base class. (For more information about virtual functions, see Virtual Functions in Chapter 9.)


Representing Pointers to Members of Classes Using Inheritance

Declaring a pointer to a member of a class prior to the class definition impacts the size and speed of the resulting executable file. The number of bytes required to represent a pointer to a member of a class and the code required to interpret the representation may depend on whether the class is defined with no, single, multiple, or virtual inheritance.

In general, the more complex the inheritance used by a class, the greater the number of bytes required to represent a pointer to a member of the class and the larger the code required to interpret the pointer.

If you need to declare a pointer to a member of a class prior to defining the class, you must use either the /vmg command-line option or the related pointers_to_members pragma. Or you can specify the inheritance used in the class declaration using the __single_inheritance, __multiple_inheritance, or __virtual_inheritance keywords, thus allowing control of the code generated on a per-class basis. These options are explained in the following.

Note If you always declare a pointer to a member of a class after defining the class, you don’t need to use any of these options.

Microsoft attempts to optimize the representation and code generated for pointers to members by selecting the most compact representation possible. This requires defining the class the pointer to member is based upon at the point where the pointer to member is declared. The pointers_to_members pragma allows you to relax this restriction and to control the pointer size and the code required to interpret the pointer.

Syntax

#pragma pointers_to_members( pointer-declaration, [most-general-representation] )

The pointer-declaration argument specifies whether you have declared a pointer to a member before or after the associated function definition. The pointer-declaration argument can be either full_generality or best_case.

The most-general-representation argument specifies the smallest pointer representation that the compiler can safely use to reference any pointer to a member of a class in a translation unit. This argument can be single_inheritance, multiple_inheritance, or virtual_inheritance.

The pointers_to_members pragma with the best_case argument is the compiler default. You can use this default if you always define a class before declaring a pointer to a member of the class. When the compiler encounters the declaration of a pointer to a member of a class, it already has knowledge of the kind of inheritance used by the class. Thus, the compiler can use the smallest possible representation of a pointer and generate the smallest amount of code required to operate on the pointer for each kind of inheritance. This is equivalent to using /vmb on the command-line to specify best-case representation for all classes in the compilation unit.

Use the pointers_to_members pragma with the full_generality argument if you need to declare a pointer to a member of a class before defining the class. (This need can arise if you define members in two different classes that reference each other using pointers to members. For such mutually referencing classes, one class must be referenced before it is defined.) The compiler uses the most general representation for the pointer to the member. This is equivalent to the /vmg compiler option. If you specify full-generality, you must also specify single-inheritance, multiple-inheritance, or virtual-inheritance. This is equivalent to using the /vmg compiler option with the /vms, /vmm, or /vmv option.

The pointers_to_members pragma with the full_generality, single_inheritance arguments (/vms option with the /vmg option) specifies that the most general representation of a pointer to a member of a class is one that uses no inheritance or single inheritance. This is the smallest possible representation of a pointer to a member of a class. The compiler generates an error if the inheritance model of a class definition for which a pointer to a member is declared is multiple or virtual. For example, placing this statement

#pragma pointers_to_members(full_generality, single_inheritance)

before a class definition declares that all class definitions that follow use only single inheritance. Once specified, the option specified with the pointers_to_members pragma cannot be changed.

The pointers_to_members pragma with the full_generality, multiple_inheritance arguments (/vmm option with the /vmg option) specifies that the most general representation of a pointer to a member of a class is one that uses multiple inheritance. This representation is larger than that required for single inheritance. The compiler generates an error if the inheritance model of a class definition for which a pointer to a member is declared is virtual.

The pointers_to_members pragma with the full_generality, virtual_inheritance arguments (/vmv option with the /vmg option) specifies that the most general representation of a pointer to a member of a class is one that uses virtual inheritance. In terms of pointer size and the code required to interpret the pointer, this is the most expensive option. However, this option never causes an error and is the default when the full_generality argument to the pointers_to_members pragma is specified or when the /vmg command-line option is used.

Syntax

The equivalent language construction uses this syntax:

class-declaration :

class inheritance-typeopt class-name;

inheritance-type :

__single_inheritance
__multiple_inheritance
__virtual_inheritance

As shown in this example,

class __single_inheritance S;
int S::p;

regardless of compiler options or pragmas, pointers to members of class S will use the smallest possible representation.

You can also explicitly give a forward declaration to the pointer-to-member representation of a class that has a forward declaration.

Note The same forward declaration of a class pointer-to-member representation should occur in every translation unit that declares pointers to members of that class, and the declaration should occur before the pointers to members are declared.


Array

An array is a collection of like objects. The simplest case of an array is a vector. C++ provides a convenient syntax for declaration of fixed-size arrays:

Syntax

decl-specifiers dname [ constant-expressionopt ] ;

The number of elements in the array is given by the constant-expression. The first element in the array is the 0th element, and the last element is the (n-1th) element, where n is the size of the array. The constant-expression must be of an integral type and must be greater than 0. A zero-sized array is legal only when the array is the last field in a struct or union and when the Microsoft extensions (/Ze) are enabled.

Arrays are derived types and can therefore be constructed from any other derived or fundamental type except functions, references, and void.

Arrays constructed from other arrays are multidimensional arrays. These multidimensional arrays are specified by placing multiple [ constant-expression ] specifications in sequence. For example, consider this declaration:

int i2[5][7];

It specifies an array of type int, conceptually arranged in a two-dimensional matrix of five rows and seven columns, as shown in Figure 7.2.

Figure 7.2 Conceptual Layout of Multidimensional Array

In declarations of multidimensioned arrays that have an initializer-list (as described in Initializers), the constant-expression that specifies the bounds for the first dimension can be omitted. For example:

const int cMarkets = 4;

// Declare a float that represents the transportation costs.
double TransportCosts[][cMarkets] =
{ { 32.19, 47.29, 31.99, 19.11 },
  { 11.29, 22.49, 33.47, 17.29 },
  { 41.97, 22.09,  9.76, 22.55 }  };

The preceding declaration defines an array that is three rows by four columns. The rows represent factories and the columns represent markets to which the factories ship. The values are the transportation costs from the factories to the markets. The first dimension of the array is left out, but the compiler fills it in by examining the initializer.

The technique of omitting the bounds specification for the first dimension of a multidimensioned array can also be used in function declarations as follows:

#include <float.h>         // Includes DBL_MAX.
#include <iostream.h>

const int    cMkts = 4;

// Declare a float that represents the transportation costs.
double TransportCosts[][cMkts] =
{ { 32.19, 47.29, 31.99, 19.11 },
  { 11.29, 22.49, 33.47, 17.29 },
  { 41.97, 22.09,  9.76, 22.55 }  };
// Calculate size of unspecified dimension.
const int cFactories = sizeof TransportCosts /
                       sizeof( double[cMkts] );

double FindMinToMkt( int Mkt, double TransportCosts[][cMkts],
                     int cFacts );

void main( int argc, char *argv[] )
{
    double MinCost;
    MinCost = FindMinToMkt( *argv[1] - '0', TransportCosts,
                            cFacts );
    cout << "The minimum cost to Market " << argv[1] << " is: "
         << MinCost << "\n";
}

double FindMinToMkt( int Mkt, double TransportCosts[][cMkts],
                     int cFacts )
{
    double MinCost = DBL_MAX;
    for( int i = 0; i < cFacts; ++i )
        MinCost = (MinCost < TransportCosts[i][Mkt]) ?
                   MinCost : TransportCosts[i][Mkt];
    return MinCost;
}

The function FindMinToMkt is written such that adding new factories does not require any code changes, just a recompilation.


Using Arrays

Individual elements of arrays are accessed using the array subscript operator ([ ]). If a singly dimensioned array is used in an expression with no subscript, the array name evaluates to a pointer to the first element in the array. For example:

char chArray[10];

...

char *pch = chArray;      // Pointer to first element.
char   ch = chArray[0];   // Value of first element.
       ch = chArray[3];   // Value of fourth element.

When using multidimensioned arrays, various combinations are acceptable in expressions. The following example illustrates this:

double multi[4][4][3]; // Declare the array.

double (*p2multi)[3];
double (*p1multi);

cout << multi[3][2][3] << "\n";   // Use three subscripts.
p2multi = multi[3];               // Make p2multi point to
                                  //  fourth "plane" of multi.
p1multi = multi[3][2];            // Make p1multi point to
                                  //  fourth plane, second row
                                  //  of multi.

In the preceding code, multi is a three-dimensional array of type double. The p2multi pointer points to an array of type double of size three. The array is used with one, two, and three subscripts in this example. Although it is more common to specify all the subscripts, as in the cout statement, it is sometimes useful to select a specific subset of array elements as shown in the succeeding statements.


Arrays in Expressions

When an identifier of an array type appears in an expression other than sizeof, address-of (&), or initialization of a reference, it is converted to a pointer to the first array element. For example:

char szError1[] = "Error: Disk drive not ready.";
char *psz = szError1;

The pointer psz points to the first element of the array szError1. Note that arrays, unlike pointers, are not modifiable l-values. Therefore, the following assignment is illegal:

szError1 = psz;


Interpretation of Subscript Operator

Like other operators, the subscript operator ([ ]) can be redefined by the user. The default behavior of the subscript operator, if not overloaded, is to combine the array name and the subscript using the following method:

*((array-name) + (subscript))

As in all addition that involves pointer types, scaling is performed automatically to adjust for the size of the type. Therefore, the resultant value is not subscript bytes from the origin of array-name; rather, it is the subscriptth element of the array. (For more information about this conversion, see Additive Operators in Chapter 4.)

Similarly, for multidimensional arrays, the address is derived using the following method:

*((array-name) + (subscript1* max2 * max3...maxn)
+ subscript2 * max3...maxn)
. . . + subscriptn))


Indirection on Array Types

Use of the indirection operator (*) on an n-dimensional array type yields an n–1 dimensional array. If n is 1, a scalar (or array element) is yielded.


Ordering of C++ Arrays

C++ arrays are stored in row-major order. Row-major order means the last subscript varies the fastest.


Function Declarations

This section includes the following topics:

  • Function declaration syntax
    • Variable argument lists

    • Declaring functions that take no arguments

    • Function overloading

    • Restrictions on functions

    • The argument declaration list

    • Argument lists in function prototypes (nondefining declaration)

    • Argument lists in function definitions
  • Default arguments
    • Default argument expressions

    • Other considerations

Function definition is covered in Function Definitions.


Function Declaration Syntax

Syntax

decl-specifiers dname( argument-declaration-list ) cv-mod-listopt

argument-declaration-list :

arg-declaration-list , ...

arg-declaration-list :

argument-declaration
arg-declaration-list , argument-declaration

argument-declaration :

decl-specifiers declarator
decl-specifiers declarator = expression
decl-specifiers abstract-declaratoropt
decl-specifiers abstract-declaratoropt = expression

The identifier given by dname has the type “cv-mod-list function, taking argument-declaration-list, and returning type decl-specifiers.”

Note that const, volatile, and many of the Microsoft-specific keywords can appear in cv-mod-list and in the declaration of the name. The following example shows two simple function declarations:

char *strchr( char *dest, char *src );
static int atoi( const char *ascnum ) const;

The following syntax explains the details of a function declaration:

Syntax

argument-declaration-list :

arg-declaration-listopt ...opt
arg-declaration-list , ...

arg-declaration-list :

argument-declaration
arg-declaration-list , argument-declaration

argument-declaration :

decl-specifiers declarator
decl-specifiers declarator , expression
decl-specifiers abstract-declaratoropt
decl-specifiers abstract-declaratoropt , expression


Variable Argument Lists

Function declarations in which the last member of argument-declaration-list is the ellipsis (...) can take a variable number of arguments. In these cases, C++ provides type checking only for the explicitly declared arguments. You can use variable argument lists when you need to make a function so general that even the number and types of arguments can vary. The printf family of functions is an example of functions that use variable argument lists.

To access arguments after those declared, use the macros contained in the standard include file STDARG.H as described in Functions with Variable Argument Lists.

Microsoft Specific

Microsoft C++ allows the ellipsis to be specified as an argument if the ellipsis is the first argument and the ellipsis is preceded by a comma. Therefore, the declaration int Func( int i, ... ); is legal, but int Func( int i ... ); is not.

END Microsoft Specific

Declaration of a function that takes a variable number of arguments requires at least one “placeholder” argument, even if it is not used. If this place-holder argument is not supplied, there is no way to access the remaining arguments.

When arguments of type char are passed as variable arguments, they are converted to type int. Similarly, when arguments of type float are passed as variable arguments, they are converted to type double. Arguments of other types are subject to the usual integral and floating-point promotions. See Integral Promotions in Chapter 3 for more information.


Declaring Functions That Take No Arguments

A function declared with the single keyword void in argument-declaration-list takes no arguments, as long as the keyword void is the first and only member of argument-declaration list. Arguments of type void elsewhere in argument-declaration-list produce errors. For example:

long GetTickCount( void );            // OK
long GetTickCount( int Reset, void ); // Error
long GetTickCount( void, int Reset ); // Error

In C++, explicitly specifying that a function requires no arguments is the same as declaring a function with no argument-declaration-list. Therefore, the following two statements are identical:

long GetTickCount();
long GetTickCount( void );

Note that, while it is illegal to specify a void argument except as outlined here, types derived from type void (such as pointers to void and arrays of void) can appear anywhere in argument-declaration-list.


Function Overloading

C++ allows specification of more than one function of the same name in the same scope. These are called “overloaded functions” and are described in detail in Chapter 12, Overloading. Overloaded functions enable programmers to supply different semantics for a function, depending on the types and number of arguments.

For example, a print function that takes a string (or char *) argument performs very different tasks than one that takes an argument of type double. Overloading permits uniform naming and prevents programmers from having to invent names such as print_sz or print_d. Table 7.3 shows what parts of a function declaration C++ uses to differentiate between groups of functions with the same name in the same scope.

Table 7.3 Overloading Considerations

Function Declaration Element | Used for Overloading?
Function return type | No
Number of arguments | Yes
Type of arguments | Yes
Presence or absence of ellipsis | Yes
Use of typedef names | No
Unspecified array bounds | No
const or volatile (in cv-mod-list) | Yes

Although functions can be distinguished on the basis of return type, they cannot be overloaded on this basis.

The following example illustrates how overloading can be used. Another way to solve the same problem is presented in Default Arguments.

#include <iostream.h>
#include <math.h>
#include <stdlib.h>

// Prototype three print functions.
int print( char *s );                  // Print a string.
int print( double dvalue );            // Print a double.
int print( double dvalue, int prec );  // Print a double with a
                                       //  given precision.
void main( int argc, char *argv[] )
{
    const double d = 893094.2987;

    if( argc < 2 )
    {
        // These calls to print invoke print( char *s ).
        print( "This program requires one argument." );
        print( "The argument specifies the number of" );
        print( "digits precision for the second number" );
        print( "printed." );
    }

    // Invoke print( double dvalue ).
    print( d );

    // Invoke print( double dvalue, int prec ).
    print( d, atoi( argv[1] ) );
}

// Print a string.
int print( char *s )
{
    cout << s << endl;
    return cout.good();
}

// Print a double in default precision.
int print( double dvalue )
{
    cout << dvalue << endl;
    return cout.good();
}

// Print a double in specified precision.
//  Positive numbers for precision indicate how many digits'
//  precision after the decimal point to show. Negative
//  numbers for precision indicate where to round the number
//  to the left of the decimal point.
int print( double dvalue, int prec )
{
    // Use table-lookup for rounding/truncation.
    static const double rgPow10[] = {
        10E-7, 10E-6, 10E-5, 10E-4, 10E-3, 10E-2, 10E-1, 10E0,
        10E1,  10E2,  10E3,  10E4, 10E5,  10E6
    };
    const int iPowZero = 6;

    // If precision out of range, just print the number.
    if( prec < -6 || prec > 7 )
        return print( dvalue );

    // Scale, truncate, then rescale.
    dvalue = floor( dvalue / rgPow10[iPowZero - prec] ) *
                             rgPow10[iPowZero - prec];

    cout << dvalue << endl;
    return cout.good();
}

The preceding code shows overloading of the print function in file scope.

For restrictions on overloading and information on how overloading affects other elements of C++, see Chapter 12, Overloading.


Restrictions on Functions

Functions cannot return arrays or functions. They can, however, return references or pointers to arrays or functions. Another way to return an array is to declare a structure with only that array as a member:

struct Address
{ char szAddress[31]; };

Address GetAddress();

It is illegal to define a type in either the return-type portion of a function declaration or in the declaration of any argument to a function. The following legal C code is illegal in C++:

enum Weather { Cloudy, Rainy, Sunny } GetWeather( Date Today )

The preceding code is disallowed because the type Weather has function scope local to GetWeather and the return value cannot be properly used. Because arguments to functions have function scope, declarations made within the argument list would have the same problem if not allowed.

C++ does not support arrays of functions. However, arrays of pointers to functions can be useful. In parsing a Pascal-like language, the code is often separated into a lexical analyzer that parses tokens and a parser that attaches semantics to the tokens. If the analyzer returns a particular ordinal value for each token, code can be written to perform appropriate processing as shown in this example:

int ProcessFORToken( char *szText );
int ProcessWHILEToken( char *szText );
int ProcessBEGINToken( char *szText );
int ProcessENDToken( char *szText );
int ProcessIFToken( char *szText );
int ProcessTHENToken( char *szText );
int ProcessELSEToken( char *szText );
int (*ProcessToken[])( char * ) = {
    ProcessFORToken, ProcessWHILEToken, ProcessBEGINToken,
    ProcessENDToken, ProcessIFToken, ProcessTHENToken,
    ProcessELSEToken };
const int MaxTokenID = sizeof ProcessToken / sizeof( int (*)() );

...
int DoProcessToken( int TokenID, char *szText )
{
    if( TokenID < MaxTokenID )
        return (*ProcessToken[TokenID])( szText );
    else
        return Error( szText );
}


The Argument Declaration List

The argument-declaration-list portion of a function declaration:

  • Allows the compiler to check type consistency among the arguments the function requires and the arguments supplied in the call.

  • Enables conversions, either implicit or user-defined, to be performed from the supplied argument type to the required argument type.

  • Checks initializations of, or assignments to, pointers to functions.

  • Checks initializations of, or assignments to, references to functions.


Argument Lists in Function Prototypes (Nondefining Declaration)

The form argument-declaration-list is a list of the type names of the arguments. Consider an argument-declaration-list for a function, func, that takes these three arguments: pointer to type char, char, and int.

The code for such an argument-declaration-list can be written:

char *, char, int

The function declaration (the prototype) might therefore be written:

void func( char *, char, int );

Although the preceding declaration contains enough information for the compiler to perform type checking and conversions, it does not provide much information about what the arguments are. A good way to document function declarations is to include identifiers as they would appear in the function definition, as in the following:

void func( char *szTarget, char chSearchChar, int nStartAt );

These identifiers in prototypes are useful only for default arguments, because they go out of scope immediately. However, they provide meaningful program documentation.


Argument Lists in Function Definitions

The argument list in a function definition differs from that of a prototype only in that the identifiers, if present, represent formal arguments to the function. The identifier names need not match those in the prototype (if there are any).

Note It is possible to define functions with unnamed arguments. However, these arguments are inaccessible to the functions for which they are defined.


Default Arguments

In many cases, functions have arguments that are used so infrequently that a default value would suffice. To address this, the default-argument facility allows for specifying only those arguments to a function that are meaningful in a given call. To illustrate this concept, consider the example presented in Function Overloading.

// Prototype three print functions.
int print( char *s );                  // Print a string.
int print( double dvalue );            // Print a double.
int print( double dvalue, int prec );  // Print a double with a
                                       //  given precision.

In many applications, a reasonable default can be supplied for prec, eliminating the need for two functions:

// Prototype two print functions.
int print( char *s );                    // Print a string.
int print( double dvalue, int prec=2 );  // Print a double with a
                                         //  given precision.

The implementation of the print function is changed slightly to reflect the fact that only one such function exists for type double:

// Print a double in specified precision.
//  Positive numbers for precision indicate how many digits'
//  precision after the decimal point to show. Negative
//  numbers for precision indicate where to round the number
//  to the left of the decimal point.
int print( double dvalue, int prec )
{
    // Use table-lookup for rounding/truncation.
    static const double rgPow10[] = {
        10E-7, 10E-6, 10E-5, 10E-4, 10E-3, 10E-2, 10E-1, 10E0,
        10E1,  10E2,  10E3,  10E4, 10E5,  10E6
    };
    const int iPowZero = 6;
// If precision out of range, just print the number.
    if( prec >= -6 || prec <= 7 )
        // Scale, truncate, then rescale.
        dvalue = floor( dvalue / rgPow10[iPowZero - prec] ) *
                                 rgPow10[iPowZero - prec];

    cout << dvalue << endl;

    return cout.good();
}

To invoke the new print function, use code such as the following:

print( d );    // Precision of 2 supplied by default argument.
print( d, 0 ); // Override default argument to achieve other
               //  results.

Note these points when using default arguments:

  • Default arguments are used only in function calls where trailing arguments are omitted — they must be the last argument(s). Therefore, the following code is illegal:
    int print( double dvalue = 0.0, int prec );
  • A default argument cannot be redefined in later declarations even if the redefinition is identical to the original. Therefore, the following code produces an error:
    // Prototype for print function.
int print( double dvalue, int prec = 2 );

...

// Definition for print function.
int print( double dvalue, int prec = 2 )
{
...
}

    The problem with this code is that the function declaration in the definition redefines the default argument for prec.

  • Additional default arguments can be added by later declarations.

  • Default arguments can be provided for pointers to functions. For example:
    int (*pShowIntVal)( int i = 0 );


Default Argument Expressions

The expressions used for default arguments are often constant expressions, but this is not a requirement. The expression can combine functions that are visible in the current scope, constant expressions, and global variables. The expression cannot contain local variables or nonstatic class-member variables. The following code illustrates this:

BOOL CreateVScrollBar( HWND hWnd, short nWidth =
                       GetSystemMetrics( SM_CXVSCROLL ) );

The preceding declaration specifies a function that creates a vertical scroll bar of a given width for a window. If no width argument is supplied, the Windows API function, GetSystemMetrics, is called to find the default width for a scroll bar.

The default expression is evaluated after the function call, but the evaluation is completed before the function call actually takes place.

Because formal arguments to a function are in function scope, and because the evaluation of default arguments takes place prior to entry to this scope, you cannot use formal arguments, or local variables in default argument expressions.

Note that any formal argument declared before a default argument expression can hide a global name in the function scope, which can cause errors. The following code is illegal:

const int Categories = 9;

void EnumCategories( char *Categories[], int n = Categories );

In the preceding code, the global name Categories is hidden at function scope, making the default argument expression invalid.


Other Considerations

The default argument is not considered part of the function type. Therefore, it is not used in selecting overloaded functions. Two functions that differ only in their default arguments are considered multiple definitions rather than overloaded functions.

Default arguments cannot be supplied for overloaded operators.


C++ Function Definitions

Function definitions differ from function declarations in that they supply function bodies — the code that makes up the function.

Syntax

function-definition :

decl-specifiersopt declarator ctor-initializeropt fct-body

fct-body :

compound-statement

As discussed in Functions, the form of the declarator in the syntax is:

dname ( argument-declaration-list ) cv-mod-listopt

The formal arguments declared in argument-declaration-list are in the scope of the function body.

Figure 7.3 shows the parts of a function definition. The shaded area is the function body.

Figure 7.3 Parts of a Function Definition

The cv-mod-list element of the declarator syntax specifies how the this pointer is to be treated; it is only for use with class member functions.

The ctor-initializer element of the syntax is used only in constructors. Its purpose is to allow initialization of base classes and contained objects. (For more information about use of ctor-initializer, see Initializing Bases and Members in Chapter 11.)


Functions with Variable Argument Lists

Functions that require variable lists are declared using the ellipsis (...) in the argument list, as described in Variable Argument Lists. To access arguments passed to functions using this method, use the types and macros described in the STDARG.H standard include file.

The following example shows how the va_start, va_arg, and va_end macros, along with the va_list type (declared in STDARG.H), work together:

#include <stdio.h>
#include <stdarg.h>

//  Declaration, but not definition, of ShowVar.
int ShowVar( char *szTypes, ... );

void main()
{
    ShowVar( "fcsi", 32.4f, 'a', "Test string", 4 );
}
//  ShowVar takes a format string of the form
//   "ifcs", where each character specifies the
//   type of the argument in that position.
//
//  i = int
//  f = float
//  c = char
//  s = string (char *)
//
//  Following the format specification is a list
//   of n arguments, where n == strlen( szTypes ).
void ShowVar( char *szTypes, ... )
{
    va_list vl;
    int i;

    //  szTypes is the last argument specified; all
    //   others must be accessed using the variable-
    //   argument macros.
    va_start( vl, szTypes );

    // Step through the list.
    for( i = 0; szTypes[i] != '\0'; ++i )
    {
        union Printable_t
        {
            int     i;
            float   f;
            char    c;
            char   *s;
        } Printable;

        switch( szTypes[i] )    // Type to expect.
        {
        case 'i':
            Printable.i = va_arg( vl, int );
            printf( "%i\n", Printable.i );
            break;

        case 'f':
            Printable.f = va_arg( vl, float );
            printf( "%f\n", Printable.f );
            break;

        case 'c':
            Printable.c = va_arg( vl, char );
            printf( "%c\n", Printable.c );
            break;

        case 's':
            Printable.s = va_arg( vl, char * );
            printf( "%s\n", Printable.s );
            break;

        default:
            break;
        }
    }
    va_end( vl );
}

The preceding example illustrates these important concepts:

  • A list marker must be established as a variable of type va_list before any variable arguments are accessed. In the preceding example, the marker is called vl.

  • The individual arguments are accessed using the va_arg macro. The va_arg macro needs to be told the type of argument to retrieve so it can transfer the correct number of bytes from the stack. If an incorrect type of a size different than that supplied by the calling program is specified to va_arg, the results are unpredictable.

  • The result obtained using the va_arg macro should be explicitly cast to the desired type.

  • The va_end macro must be called to terminate variable-argument processing.


Initializers

Declarators can specify the initial value for objects. The only way to specify a value for objects of const type is in the declarator. The part of the declarator that specifies this initial value is called the “initializer.”

Syntax

initializer :

= assignment-expression
= { initializer-list ,opt }
( expression-list )

initializer-list :

expression
initializer-list , expression
{ initializer-list ,opt }

There are two fundamental types of initializers:

  • The initializer invoked using the equal-sign syntax

  • The initializer invoked using function-style syntax

Only objects of classes with constructors can be initialized with the function-style syntax. The two syntax forms also differ in access control and in the potential use of temporary objects. Consider the following code, which illustrates some declarators with initializers:

int      i = 7;                  // Uses equal-sign syntax.
Customer Cust( "Taxpayer, Joe",  // Uses function-style
               "14 Cherry Lane", //  syntax. Requires presence
               "Manteca",        //  of a constructor.
               "CA" );

Declarations of automatic, register, static, and external variables can contain initializers. However, declarations of external variables can contain initializers only if the variables are not declared as extern.

These initializers can contain expressions involving constants and variables in the current scope. The initializer expression is evaluated at the point the declaration is encountered in program flow, or, for global static objects and variables, at program startup. (For more information about initialization of global static objects, see Additional Startup Considerations in Chapter 2.)


Initializing Pointers to const Objects

A pointer to a const object can be initialized with a pointer to an object that is not const, but not vice versa. For example, the following initialization is legal:

Window StandardWindow;
const Window* pStandardWindow( &StandardWindow );

In the preceding code, the pointer pStandardWindow is declared as a pointer to a const object. Although StandardWindow is not declared as const, the declaration is acceptable because it does not allow an object not declared as const access to a const object. The reverse of this is as follows:

const Window StandardWindow;
Window* pStandardWindow( &StandardWindow );

The preceding code explicitly declares StandardWindow as a const object. Initializing the nonconstant pointer pStandardWindow with the address of StandardWindow generates an error because it allows access to the const object through the pointer. That is, it allows removal of the const attribute from the object.


Uninitialized Objects

Objects and simple variables of storage class static that are declared with no initializer are guaranteed to be initialized to a bit pattern of zeros. No such special processing takes place for uninitialized objects of automatic or register storage classes. They have undefined values.


Initializing Static Members

Static member initialization occurs in class scope. Therefore, they can access other member data or functions. For example:

class DialogWindow
{
public:
    static short  GetTextHeight();
private:
    static short nTextHeight;
};

short DialogWindow :: nTextHeight = GetTextHeight();

Note that in the preceding definition of the static member nTextHeight, GetTextHeight is implicitly known to be DialogWindow :: GetTextHeight.


Initializing Aggregates

An aggregate type is an array, class, or structure type which:

  • Has no constructors

  • Has no nonpublic members

  • Has no base classes

  • Has no virtual functions

Initializers for aggregates can be specified as a comma-separated list of values enclosed in curly braces. For example, this code declares an int array of 10 and initializes it:

int rgiArray[10] = { 9, 8, 4, 6, 5, 6, 3, 5, 6, 11 };

The initializers are stored in the array elements in increasing subscript order. Therefore, rgiArray[0] is 9, rgiArray[1] is 8, and so on, until rgiArray[9], which is 11. To initialize a structure, use code such as:

struct RCPrompt
{
    short nRow;
    short nCol;
    char *szPrompt;
};
RCPrompt rcContinueYN = { 24, 0, "Continue (Y/N?)" };


Length of Aggregate-Initializer Lists

If an aggregate initializer list is shorter than the array or class type that is being initialized, zeros are stored in the elements for which no initializer is specified. Therefore, the following two declarations are equivalent:

// Explicitly initialize all elements.
int rgiArray[5] = { 3, 2, 0, 0, 0 };

// Allow remaining elements to be zero-initialized.
int rgiArray[5] = { 3, 2 };

As this shows, initializer lists can be truncated but supplying too many initializers generates an error.


Initializing Aggregates That Contain Aggregates

Some aggregates contain other aggregates — for example, arrays of arrays, arrays of structures, or structures that are composed of other structures. Initializers can be supplied for such constructs by initializing each one in the order it occurs with a brace-enclosed list. For example:

// Declare an array of type RCPrompt.
RCPrompt rgRCPrompt[4] =
{ { 4,  7, "Options Are:"  },
  { 6,  7, "1. Main Menu"  },
  { 8,  7, "2. Print Menu" },
  { 10, 7, "3. File Menu"  } };

Note that rgRCPrompt is initialized with a brace-enclosed list of brace-enclosed lists. The enclosed braces are not syntactically required, but they lend clarity to the declaration. The following example program shows how a two-dimensional array is filled by such an initializer:

#include <iostream.h>

void main()
{
    int rgI[2][4] = { 1, 2, 3, 4, 5, 6, 7, 8 };

    for( int i = 0; i < 2; ++i )
        for( int j = 0; j < 4; ++j )
            cout << "rgI[" << i << "][" << j << "] = "
                 << rgI[i][j] << endl;
}

The output from this program is:

rgI[0][0] = 1
rgI[0][1] = 2
rgI[0][2] = 3
rgI[0][3] = 4
rgI[1][0] = 5
rgI[1][1] = 6
rgI[1][2] = 7
rgI[1][3] = 8

Short initialization lists can be used only with explicit subaggregate initializers and enclosed in braces. If rgI had been declared as:

int rgI[2][4] = { { 1, 2 }, { 3, 4 } };

the program output would have been:

rgI[0][0] = 1
rgI[0][1] = 2
rgI[0][2] = 0
rgI[0][3] = 0
rgI[1][0] = 3
rgI[1][1] = 4
rgI[1][2] = 0
rgI[1][3] = 0


Initializing Incomplete Types

Incomplete types, such as unbounded array types, can be initialized as follows:

char HomeRow[] = { 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l' };

The compiler computes the size of the array from the number of initializers provided.

Incomplete types, such as pointers to class types that are declared but not defined, are declared as follows:

class DefinedElsewhere;        // Class definition elsewhere.
class DefinedHere
{
    ...
    friend class DefinedElsewhere;
};


Initializing Using Constructors

Objects of class type are initialized by calling the appropriate constructor for the class. For complete information about initializing class types, see Explicit Initialization in Chapter 11.


Initializers and Unions

Objects of union type are initialized with a single value (if the union does not have a constructor). This is done in one of two ways:

  • Initialize the union with another object of the same union type. For example:
    struct Point
{
    unsigned x;
    unsigned y;
};
union PtLong
{
    long  l;
    Point pt;
};

...

PtLong ptOrigin;
PtLong ptCurrent = ptOrigin;

    In the preceding code, ptCurrent is initialized with the value of ptOrigin — an object of the same type.

  • Initialize the union with a brace-enclosed initializer for the first member. For example:
    PtLong ptCurrent = { 0x0a000aL };


Initializing Character Arrays

Character arrays can be initialized in one of two ways:

  • Individually, as follows:
    char chABCD[4] = { 'a', 'b', 'c', 'd' };
  • With a string, as follows:
    char chABCD[5] = "abcd";

In the second case, where the character array is initialized with a string, the compiler appends a trailing '\0' (end-of-string character). Therefore, the array must be at least one larger than the number of characters in the string.

Because most string handling uses the standard library functions or relies on the presence of the trailing end-of-string character, it is common to see unbounded array declarations initialized with strings:

char chABCD[] = "ABCD";


Initializing References

Variables of reference type must be initialized with an object of the type from which the reference type is derived, or with an object of a type that can be converted to the type from which the reference type is derived. For example:

int  iVar;
long lVar;

long& LongRef1 = lVar;      // No conversion required.
long& LongRef2 = iVar;      // Error.
const long& LongRef3 = iVar // OK

LongRef1 = 23L;        // Change lVar through a reference.
LongRef2 = 11L;        // Change iVar through a reference.
LongRef3 = 11L;        // Error.

The only way to initialize a reference with a temporary object is to initialize a constant temporary object. Once initialized, a reference-type variable always points to the same object; it cannot be modified to point to another object.

Although the syntax can be the same, initialization of reference-type variables and assignment to reference-type variables are semantically different. In the preceding example, the assignments that change iVar and lVar look similar to the initializations but have different effects. The initialization specifies the object to which the reference-type variable points; the assignment assigns to the referred-to object through the reference.

Because both passing an argument of reference type to a function and returning a value of reference type from a function are initializations, the formal arguments to a function are initialized correctly, as are the references returned.

Reference-type variables can be declared without initializers only in the following:

  • Function declarations (prototypes). For example:
    int func( int& );
  • Function-return type declarations. For example:
    int& func( int& );
  • Declaration of a reference-type class member. For example:
    class c
{
public:
    int& i;
};
  • Declaration of a variable explicitly specified as extern. For example:
    extern int& iVal;

When initializing a reference-type variable, the compiler uses the decision graph shown in Figure 7.4 to select between creating a reference to an object or creating a temporary object to which the reference points.

References to volatile types (declared as volatile typename& identifier) can be initialized with volatile objects of the same type or with objects that have not been declared as volatile. They cannot, however, be initialized with const objects of that type. Similarly, references to const types (declared as const typename& identifier) can be initialized with const objects of the same type (or anything that has a conversion to that type or with objects that have not been declared as const). They cannot, however, be initialized with volatile objects of that type.

References that are not qualified with either the const or volatile keyword can be initialized only with objects declared as neither const nor volatile.

Figure 7.4 Decision Graph for Initialization of Reference Types


Classes

This chapter introduces C++ classes. Classes, which can contain data and functions, introduce user-defined types into a program. User-defined types in traditional programming languages are collections of data which, taken together, describe an object’s attributes and state. Class types in C++ enable you to describe attributes and state, and to define behavior.

The following topics are included:

  • Overview

  • Class names

  • Class members

  • Member functions

  • Static data members

  • Unions

  • Bit fields

  • Nested class declarations

  • Type names in class scope


Overview of Classes

Class types are defined using the class, struct, and union keywords. For simplicity, types defined with these keywords are called class declarations, except in discussions of language elements that behave differently depending on which keyword is used.

Names of classes defined within another class (“nested”) have class scope of the enclosing class.

Syntax

class-name:

identifier

The variables and functions of a class are called members. When defining a class, it is common practice to supply the following members (although all are optional):

  • Class data members, which define the state and attributes of an object of the class type.

  • One or more “constructor” functions, which initialize an object of the class type. Constructors are described in Constructors in Chapter 11.

  • One or more “destructor” functions, which perform cleanup functions such as deallocating dynamically allocated memory or closing files. Destructors are described in Destructors in Chapter 11.

  • One or more member functions that define the object’s behavior.


Defining Class Types

Class types are defined using class-specifiers. Class types can be declared using elaborated-type-specifiers as shown in Type Specifiers in Chapter 6.

Syntax

class-specifier :

class-head { member-listopt }

class-head :

class-key imodelopt identifieropt base-specopt
class-key imodelopt class-nameopt base-specopt

class-key :

class
struct
union

imodel :

__declspec

Class names are introduced as identifiers immediately after the compiler processes them (before entry into the class body); they can be used to declare class members. This allows declaration of self-referential data structures, such as the following:

class Tree
{
public:
    void *Data;
    Tree *Left;
    Tree *Right;
};


Structures, Classes, and Unions

The three class types are structure, class, and union. They are declared using the struct, class, and union keywords (see class-key syntax). Table 8.1 shows the differences among the three class types.

Table 8.1 Access Control and Constraints of Structures, Classes, and Unions

Structures | Classes | Unions
class-key is struct | class-key is class | class-key is union
Default access is public | Default access is private | Default access is public
No usage constraints | No usage constraints | Use only one member at a time


Anonymous Class Types

Classes can be anonymous — that is, they can be declared without an identifier. This is useful when you replace a class name with a typedef name, as in the following:

typedef struct
{
    unsigned x;
    unsigned y;
} POINT;

Note The use of anonymous classes shown in the previous example is useful for preserving compatibility with existing C code. In some C code, the use of typedef in conjunction with anonymous structures is prevalent.

Anonymous classes are also useful when you want a reference to a class member to appear as though it were not contained in a separate class, as in the following:

struct PTValue
{
    POINT ptLoc;
    union
    {
        int  iValue;
        long lValue;
    };
};

PTValue ptv;

In the preceding code, iValue can be accessed using the object member-selection operator (.) as follows:

int i = ptv.iValue;

Anonymous classes are subject to certain restrictions. (For more information about anonymous unions, see Unions.) Anonymous classes:

  • Cannot have a constructor or destructor.

  • Cannot be passed as arguments to functions (unless type checking is defeated using ellipses).

  • Cannot be returned as return values from functions.


Point of Class Definition

A class is defined at the end of its class-specifier. Member functions need not be defined in order for the class to be considered defined. Consider the following:

class Point                    // Point class
{                              //  considered defined.
public:
    Point()
        { cx = cy = 0; }       // Constructor defined.
    Point( int x, int y )
        { cx = X, cy = Y; }    // Constructor defined.
    unsigned &x( unsigned );   // Accessor declared.
    unsigned &y( unsigned );   // Accessor declared.
private:
    unsigned  cx, cy;
};

Even though the two accessor functions (x and y) are not defined, the class Point is considered defined. (Accessor functions are functions provided to give safe access to member data.)


Class-Type Objects

An object is a typed region of storage in the execution environment; in addition to retaining state information, it also defines behavior. Class-type objects are defined using class-name. Consider the following code fragment:

class Account                      // Class name is Account.
{
public:
            Account();             // Default constructor.
            Account( double );     // Construct from double.
    double& Deposit( double );
    double& Withdraw( double, int );
    ...
}:

Account CheckingAccount;           // Define object of class type.

The preceding code declares a class (a new type) called Account. It then uses this new type to define an object called CheckingAccount.

The following operations are defined by C++ for objects of class type:

  • Assignment. One object can be assigned to another. The default behavior for this operation is a memberwise copy. This behavior can be modified by supplying a user-defined assignment operator.

  • Initialization using copy constructors.

The following are examples of initialization using user-defined copy constructors:

  • Explicit initialization of an object. For example:
    Point myPoint = thatPoint;

    declares myPoint as an object of type Point and initializes it to the value of thatPoint.

  • Initialization caused by passing as an argument. Objects can be passed to functions by value or by reference. If they are passed by value, a copy of each object is passed to the function. The default method for creating the copy is memberwise copy; this can be modified by supplying a user-defined copy constructor (a constructor that takes a single argument of the type “reference to class”).

  • Initialization caused by the initialization of return values from functions. Objects can be returned from functions by value or by reference. The default method for returning an object by value is a memberwise copy; this can be modified by supplying a user-defined copy constructor. An object returned by reference (using pointer or reference types) should not be both automatic and local to the called function. If it is, the object referred to by the return value will have gone out of scope before it can be used.

Overloaded Operators in Chapter 12 explains how to redefine other operators on a class-by-class basis.


Empty Classes

You can declare empty classes, but objects of such types still have nonzero size. The following example illustrates this:

#include <iostream.h>

class NoMembers
{
};

void main()
{
    NoMembers n;  // Object of type NoMembers.

    cout << "The size of an object of empty class is: "
         << sizeof n << endl;
}

This is the output of the preceding program:

The size of an object of empty class is: 1.

The memory allocated for such objects is of nonzero size; therefore, the objects have different addresses. Having different addresses makes it possible to compare pointers to objects for identity. Also, in arrays, each member array must have a distinct address.

Microsoft Specific

An empty base class typically contributes zero bytes to the size of a derived class.

END Microsoft Specific


Class Names

Class declarations introduce new types, called class names, into programs. These class declarations also act as definitions of the class for a given translation unit. There may be only one definition for a given class type per translation unit. Using these new class types, you can declare objects, and the compiler can perform type checking to verify that no operations incompatible with the types are performed on the objects.

An example of such type checking is:

class Point
{
public:
    unsigned x, y;
};

class Rect
{
public:
    unsigned x1, y1, x2, y2;
};

// Prototype a function that takes two arguments, one of type
//  Point and the other of type pointer to Rect.
int PtInRect( Point, Rect & );

...

Point pt;
Rect  rect;

rect = pt;   // Error. Types are incompatible.
pt = rect;   // Error. Types are incompatible.

// Error. Arguments to PtInRect are reversed.
cout << "Point is " << PtInRect( rect, pt ) ? "" : "not"
     << " in rectangle" << endl;

As the preceding code illustrates, operations (such as assignment and argument passing) on class-type objects are subject to the same type checking as objects of built-in types.

Because the compiler distinguishes between class types, functions can be overloaded on the basis of class-type arguments as well as built-in type arguments. For more information about overloaded functions, see Function Overloading in Chapter 7 and Chapter 12, Overloading.


Declaring and Accessing Class Names

Class names can be declared in global or class scope. If they are declared in class scope, they are referred to as “nested” classes.

Microsoft Specific

Function definitions are not permitted in local class declarations in Microsoft C++.

END Microsoft Specific

Any class name introduced in class scope hides other elements of the same name in an enclosing scope. Names hidden by such a declaration can then be referred to only by using an elaborated-type-specifier. The following example shows an example of using an elaborated-type-specifier to refer to a hidden name:

struct A      // Global scope definition of A.
{
    int a;
};

void main()
{
    char A = 'a'; // Redefine the name A as an object.

    struct A AObject;
    ...
}

Because the name A that refers to the structure is hidden by the A that refers to the char object, struct (a class-key) must be used to declare AObject as type A.

You can use the class-key to declare a class without providing a definition. This nondefining declaration of a class introduces a class name for forward reference. This technique is useful when designing classes that refer to one another in friend declarations. It is also useful when class names must be present in header files but the definition is not required. For example:

// RECT.H
class Point;   // Nondefining declaration of class Point.
class Line
{
public:
    int Draw( Point &ptFrom, Point &ptTo );
    ...
};

In the preceding sample, the name Point must be present, but it need not be a defining declaration that introduces the name.


typedef Statements and Classes

Using the typedef statement to name a class type causes the typedef name to become a class-name. For more information, see typedef Specifier in Chapter 6.


Class Members

Classes can have these kinds of members:

  • Member functions.

  • Data members.

  • Classes, which include classes, structures, and unions. (See Nested Class Declarations and Unions.)

  • Enumerations.

  • Bit fields.

  • Friends.

  • Type names.

Note Friends are included in the preceding list because they are contained in the class declaration. However, they are not true class members, because they are not in the scope of the class.

Syntax

member-list :

member-declaration member-listopt
access-specifier : member-listopt

member-declaration :

decl-specifiersopt member-declarator-listopt ;
function-definitionopt ;
qualified-name ;

member-declarator-list :

member-declarator
member-declarator-list , member-declarator

member-declarator :

declarator pure-specifieropt
identifieropt : constant-expression

pure-specifier :

= 0

The purpose of the member-list is to:

  • Declare the complete set of members for a given class.

  • Specify the access (public, private, or protected) associated with various class members.

In the declaration of a member list, you can declare members only once; redeclaration of members produces an error message. Because a member list is a complete set of the members, you cannot add members to a given class with subsequent class declarations.

Member declarators cannot contain initializers. Supplying an initializer produces an error message as illustrated in the following code:

class CantInit
{
public:
    long l = 7;       // Error: attempt to initialize
                      //  class member.
    static int i = 9; // Error: must be defined and initialized
                          outside of class declaration.
};

Because a separate instance of nonstatic member data is created for each object of a given class type, the correct way to initialize member data is to use the class’s constructor. (Constructors are covered in Constructors, in Chapter 11.) There is only one shared copy of static data members for all objects of a given class type. Static data members must be defined and can be initialized at file scope. (For more information about static data members, see Static Data Members.) The following example shows how to perform these initializations:

class CanInit
{
public:
    CanInit() { l = 7; } // Initializes l when new objects of type
                         //  CanInit are created.
    long       l;
    static int i;
    static int j;
};

int CanInit::i = 15;   // i is defined at file scope and
                       //  initialized to 15. The initializer
                       //  is evaluated in the scope of CanInit.
int CanInit::j = i;    // The right side of the initializer
                       //  is in the scope of the object being
                       //  initialized.

Note The class name, CanInit, must precede i to specify that the i being defined is a member of class CanInit.


Class-Member Declaration Syntax

Member data cannot be declared as auto, extern, or register storage class. They can, however, be declared as having static storage class.

The decl-specifiers specifiers can be omitted in member-function declarations. (For information on decl-specifiers, see Specifiers in Chapter 6 and Member Functions; see also Functions in Chapter 7.) The following code is therefore legal and declares a function that returns type int:

class NoDeclSpec
{
public:
   NoSpecifiers();
};

When you declare a friend class in a member list, you can omit the member-declarator-list. For more information on friends, see friend Specifier in Chapter 6, and Friends in Chapter 10. Even if a class name has not been introduced, it can be used in a friend declaration. This friend declaration introduces the name. However, in member declarations for such classes, the elaborated-type-specifier syntax must be used, as shown in the following example:

class HasFriends
{
public:
    friend class NotDeclaredYet;
};

In the preceding example, there is no member-declarator-list after the class declaration. Because the declaration for NotDeclaredYet has not yet been processed, the elaborated-type-specifier form is used: class NotDeclaredYet. A type that has been declared can be specified in a friend member declaration using a normal type specifier:

class AlreadyDeclared
{
    ...
};

class HasFriends
{
public:
    friend AlreadyDeclared;
};

The pure-specifier (shown in the following example) indicates that no implementation is supplied for the virtual function being declared. Therefore, the pure-specifier can be specified only on virtual functions. Consider this example:

class StrBase  // Base class for strings.
{
public:
    virtual int IsLessThan( StrBase& ) = 0;
    virtual int IsEqualTo( StrBase& ) = 0;
    virtual StrBase& CopyOf( StrBase& ) = 0;
    ...
};

The preceding code declares an abstract base class — that is, a class designed to be used only as the base class for more specific classes. Such base classes can enforce a particular protocol, or set of functionality, by declaring one or more virtual functions as “pure” virtual functions, using the pure-specifier.

Classes that inherit from the StrBase class must provide implementations for the pure virtual functions; otherwise, they, too, are considered abstract base classes.

Abstract base classes cannot be used to declare objects. For example, before an object of a type inherited from StrBase can be declared, the functions IsLessThan, IsEqualTo, and CopyOf must be implemented. (For more information about abstract base classes, see Abstract Classes in Chapter 9.)


Declaring Unsized Arrays in Member Lists

Microsoft Specific

Unsized arrays can be declared as the last data member in class member lists if the program is not compiled with the ANSI-compatibility option (/Za). Because this is a Microsoft extension, using unsized arrays in this way can make your code less portable. To declare an unsized array, omit the first dimension. For example:

class Symbol
{
public:
    int  SymbolType;
    char SymbolText[];
};

END Microsoft Specific


Restrictions

If a class contains an unsized array, it cannot be used as the base class for another class. In addition, a class containing an unsized array cannot be used to declare any member except the last member of another class. A class containing an unsized array cannot have a direct or indirect virtual base class.

The sizeof operator, when applied to a class containing an unsized array, returns the amount of storage required for all members except the unsized array. Implementors of classes that contain unsized arrays should provide alternate methods for obtaining the correct size of the class.

You cannot declare arrays of objects that have unsized array components. Also, performing pointer arithmetic on pointers to such objects generates an error message.


Storage of Class-Member Data

Nonstatic class-member data is stored in such a way that items falling between access specifiers are stored at successively higher memory addresses. No ordering across access specifiers is guaranteed.

Microsoft Specific

Depending on the /Zp compiler option or the pack pragma, intervening space can be introduced to align member data on word or doubleword boundaries.

In Microsoft C++, class-member data is stored at successively higher memory addresses, even though the C++ language does not require it. Basing assumptions on this ordering can lead to nonportable code.

END Microsoft Specific


Member Naming Restrictions

A function with the same name as the class in which it is declared is a constructor. A constructor is implicitly called when an object of this class type is created. (For more information about constructors, see Constructors in Chapter 11.)

The following items cannot have the same name as the classes in whose scope they are declared: data members (both static and nonstatic), enclosed enumerators, members of anonymous unions, and nested class types.


Member Functions

Classes can contain data and functions. These functions are referred to as “member functions.” Any nonstatic function declared inside a class declaration is considered a member function and is called using the member-selection operators (. and –>). When calling member functions from other member functions of the same class, the object and member-selection operator can be omitted. For example:

class Point
{
public:
    short x() { return _x; }
    short y() { return _y; }
    void  Show() { cout << x() << ", " << y() << "\n"; }
private:
    short _x, _y;
};

void main()
{
    Point pt;

    pt.Show();
}

Note that in the member function, Show, calls to the other member functions, x and y, are made without member-selection operators. These calls implicitly mean this->x() and this->y(). However, in main, the member function, Show, must be selected using the object pt and the member-selection operator (.).

Static functions declared inside a class can be called using the member-selection operators or by specifying the fully qualified function name (including the class name).

Note A function declared using the friend keyword is not considered a member of the class in which it is declared a friend (although it can be a member of another class). A friend declaration controls the access a nonmember function has to class data.

The following class declaration shows how member functions are declared:

class Point
{
public:
    unsigned GetX();
    unsigned GetY();
    unsigned SetX( unsigned x );
    unsigned SetY( unsigned y );
private:
    unsigned ptX, ptY;
};

In the preceding class declaration, four functions are declared: GetX, GetY, SetX, and SetY. The next example shows how such functions are called in a program:

void main()
{
    // Declare a new object of type Point.
    Point ptOrigin;

    // Member function calls use the . member-selection operator.
    ptOrigin.SetX( 0 );
    ptOrigin.SetY( 0 );

    // Declare a pointer to an object of type Point.
    Point *pptCurrent = new Point;
// Member function calls use the -> member-selection operator.
    pptCurrent->SetX( ptOrigin.GetX() + 10 );
    pptCurrent->SetY( ptOrigin.GetY() + 10 );
}

In the preceding code, the member functions of the object ptOrigin are called using the member-selection operator (.). However, the member functions of the object pointed to by pptCurrent are called using the –> member-selection operator.


Overview of Member Functions

Member functions are either static or nonstatic. The behavior of static member functions differs from other member functions because static member functions have no implicit this argument. Nonstatic member functions have a this pointer. Member functions, whether static or nonstatic, can be defined either in or outside the class declaration.

If a member function is defined inside a class declaration, it is treated as an inline function, and there is no need to qualify the function name with its class name. Although functions defined inside class declarations are already treated as inline functions, you can use the inline keyword to document code.

An example of declaring a function within a class declaration follows:

class Account
{
public:
    // Declare the member function Deposit within the declaration
    //  of class Account.
    double Deposit( double HowMuch )
    {
        balance += HowMuch;
        return balance;
    }
private:
    double balance;
};

If a member function’s definition is outside the class declaration, it is treated as an inline function only if it is explicitly declared as inline. In addition, the function name in the definition must be qualified with its class name using the scope-resolution operator (::).

The following example is identical to the previous declaration of class Account, except that the Deposit function is defined outside the class declaration:

class Account
{
public:
    // Declare the member function Deposit but do not define it.
    double Deposit( double HowMuch );
private:
    double balance;
};

inline double Account::Deposit( double HowMuch )
{
    balance += HowMuch;
    return balance;
}

Note Although member functions can be defined either inside a class declaration or separately, no member functions can be added to a class after the class is defined.

Classes containing member functions can have many declarations, but the member functions themselves must have only one definition in a program. Multiple definitions cause an error message at link time. If a class contains inline function definitions, the function definitions must be identical to observe this “one definition” rule.


Nonstatic Member Functions

Nonstatic member functions have an implied argument, this, that points to the object through which the function is invoked. The type of this is type * const. These functions are considered to have class scope and can use class data and other member functions in the same class scope directly. In the preceding example, the expression balance += HowMuch adds the value of HowMuch to the class member balance. Consider the following statements:

Account Checking;

Checking.Deposit( 57.00 );

The preceding code declares an object of type Account and then invokes the member function Deposit to add $57.00 to it. In the function Account::Deposit, balance is taken to mean Checking.balance (the balance member for this object).

Nonstatic member functions are intended to operate on objects of their class type. Calling such a function on objects of different types (using explicit type conversions) causes undefined behavior.


The this Pointer

All nonstatic member functions can use the this keyword, which is a const (nonmodifiable) pointer to the object for which the function was called. Member data is addressed by evaluating the expression this–>member-name (although this technique is seldom used). In member functions, using a member name in an expression implicitly uses this–>member-name to select the correct function or data member.

Note Because the this pointer is nonmodifiable, assignments to this are not allowed. Earlier implementations of C++ allowed assignments to this.

Occasionally, the this pointer is used directly — for example, to manipulate self-referential data structures, where the address of the current object is required.


Type of this Pointer

The this pointer’s type can be modified in the function declaration by the const and volatile keywords. To declare a function as having the attributes of one or more of these keywords, use the cv-mod-list grammar.

Syntax

cv-mod-list :

cv-qualifier cv-mod-listopt

cv-qualifier :

const
volatile

Consider this example:

class Point
{
    unsigned X() const;
};

The preceding code declares a member function, X, in which the this pointer is treated as a const pointer to a const object. Combinations of cv-mod-list options can be used, but they always modify the object pointed to by this, not the this pointer itself. Therefore, the following declaration declares function X; the this pointer is a const pointer to a const object:

class Point
{
    unsigned X() __far const;
};

The type of this is described by the following syntax, where cv-qualifier-list can be const or volatile, class-type is the name of the class:

cv-qualifier-listopt class-type * const this

Table 8.2 explains more about how these modifiers work.

Table 8.2 Semantics of this Modifiers

Modifier | Meaning
const | Cannot change member data; cannot invoke member functions that are not const.
volatile | Member data is loaded from memory each time it is accessed; disables certain optimizations.

It is an error to pass a const object to a member function that is not const. Similarly, it is an error to pass a volatile object to a member function that is not volatile.

Member functions declared as const cannot change member data — in such functions, the this pointer is a pointer to a const object.

Note Constructors and destructors cannot be declared as const or volatile. They can, however, be invoked on const or volatile objects.


Static Member Functions

Static member functions are considered to have class scope. In contrast to nonstatic member functions, these functions have no implicit this argument; therefore, they can use only static data members, enumerators, or nested types directly. Static member functions can be accessed without using an object of the corresponding class type. Consider this example:

class WindowManager
{
public:
    static int  CountOf();              // Return count of open windows.
           void Minimize();             // Minimize current window.
           WindowManager SideEffects(); // Function with side effects.
    ...
private:
    static int wmWindowCount;
};
int WindowManager::wmWindowCount = 0;

...

// Minimize (show iconic) all windows
for( int i = 0; i < WindowManager::CountOf(); ++i )
    rgwmWin[i].Minimize();

In the preceding code, the class WindowManager contains the static member function CountOf. This function returns the number of windows open but is not necessarily associated with a given object of type WindowManager. This concept is demonstrated in the loop where the CountOf function is used in the controlling expression; because CountOf is a static member function, it can be called without reference to an object.

Static member functions have external linkage. These functions do not have this pointers (covered in the next section). As a result, the following restrictions apply to such functions:

  • They cannot access nonstatic class member data using the member-selection operators (. or –>).

  • They cannot be declared as virtual.

  • They cannot have the same name as a nonstatic function that has the same argument types.

Note The left side of a member-selection operator (. or –>) that selects a static member function is not evaluated. This can be important if the function is used for its side effects. For example, the expression SideEffects().CountOf() does not call the function SideEffects.


Static Data Members

Classes can contain static member data and member functions. When a data member is declared as static, only one copy of the data is maintained for all objects of the class. (For more information, see Static Member Functions.)

Static data members are not part of objects of a given class type; they are separate objects. As a result, the declaration of a static data member is not considered a definition. The data member is declared in class scope, but definition is performed at file scope. These static members have external linkage. The following example illustrates this:

class BufferedOutput
{
public:
    // Return number of bytes written by any object of this class.
    short BytesWritten() { return bytecount; }

    // Reset the counter.
    static void ResetCount() { bytecount = 0; }

    // Static member declaration.
    static long bytecount;
};

// Define bytecount in file scope.
long BufferedOutput::bytecount;

In the preceding code, the member bytecount is declared in class BufferedOutput, but it must be defined outside the class declaration.

Static data members can be referred to without referring to an object of class type. The number of bytes written using BufferedOutput objects can be obtained as follows:

long nBytes = BufferedOutput::bytecount;

For the static member to exist, it is not necessary that any objects of the class type exist. Static members can also be accessed using the member-selection (. and –>) operators. For example:

BufferedOutput Console;

long nBytes = Console.bytecount;

In the preceding case, the reference to the object (Console) is not evaluated; the value returned is that of the static object bytecount.

Static data members are subject to class-member access rules, so private access to static data members is allowed only for class-member functions and friends. These rules are described in Chapter 10, Member-Access Control. The exception is that static data members must be defined in file scope regardless of their access restrictions. If the data member is to be explicitly initialized, an initializer must be provided with the definition.

The type of a static member is not qualified by its class name. Therefore, the type of BufferedOutput::bytecount is long.


Unions

Unions are class types that can contain only one data element at a time (although the data element can be an array or a class type). The members of a union represent the kinds of data the union can contain. An object of union type requires enough storage to hold the largest member in its member-list. Consider the following example:

#include <stdlib.h>
#include <string.h>
#include <limits.h>

union NumericType        // Declare a union that can hold the following:
{
    int         iValue;  // int value
    long        lValue;  // long value
    double      dValue;  // double value
};

void main( int argc, char *argv[] )
{
    NumericType *Values = new NumericType[argc - 1];

    for( int i = 1; i < argc; ++i )
        if( strchr( argv[i], '.' ) != 0 )
           // Floating type. Use dValue member for assignment.
            Values[i].dValue = atof( argv[i] );
        else
           // Not a floating type.
        {
                // If data is bigger than largest int, store it in
                //  lValue member.
            if( atol( argv[i] ) >  INT_MAX )
                Values[i].lValue = atol( argv[i] );
            else
                // Otherwise, store it in iValue member.
                Values[i].iValue = atoi( argv[i] );
        }
}

The NumericType union is arranged in memory (conceptually) as shown in Figure 8.1.

Figure 8.1 Storage of Data in NumericType Union


Member Functions in Unions

In addition to member data, unions can have member functions, as described in Member Functions. Although unions can have special functions such as constructors and destructors, unions cannot contain virtual functions. (For more information, see Constructors and Destructors in Chapter 11.)


Unions as Class Types

Unions cannot have base classes; that is, they cannot inherit the attributes of other unions, structures, or classes. Unions also cannot be used as base classes for further inheritance.

Inheritance is covered in detail in Chapter 9, Derived Classes.


Union Member Data

Unions can contain most types in their member lists, except for the following:

  • Class types that have constructors or destructors

  • Class types that have user-defined assignment operators

  • Static data members


Anonymous Unions

Anonymous unions are unions that are declared without a class-name or declarator-list.

Syntax

union { member-list } ;

Such union declarations do not declare types — they declare objects. The names declared in an anonymous union cannot conflict with other names declared in the same scope.

Names declared in an anonymous union are used directly, like nonmember variables. The following example illustrates this:

#include <iostream.h>

struct DataForm
{
    enum DataType { CharData = 1, IntData, StringData };
    DataType type;

    // Declare an anonymous union.
    union
    {
        char  chCharMem;
        char *szStrMem;
        int   iIntMem;
    };
    void print();
};

void DataForm::print()
{
    // Based on the type of the data, print the
    // appropriate data type.
    switch( type )
    {
    case CharData:
        cout << chCharMem;
        break;
    case IntData:
        cout << szStrMem;
        break;
    case StringData:
        cout << iIntMem;
        break;
    }
}

In the function DataForm::print, the three members (chCharMem, szStrMem, and iIntMem) are accessed as though they were declared as members (without the union declaration). However, the three union members share the same memory.

In addition to the restrictions listed in Union Member Data, anonymous unions are subject to additional restrictions:

  • They must also be declared as static if declared in file scope.

  • They can have only public members; private and protected members in anonymous unions generate errors.

  • They cannot have function members.

Note Simply omitting the class-name portion of the syntax does not make a union an anonymous union. For a union to qualify as an anonymous union, the declaration must not declare an object.


C++ Bit Fields

Classes and structures can contain members that occupy less storage than an integral type. These members are specified as bit fields. The syntax for bit-field member-declarator specification follows:

Syntax

declaratoropt : constant-expression

The declarator is the name by which the member is accessed in the program. It must be an integral type (including enumerated types). The constant-expression specifies the number of bits the member occupies in the structure. Anonymous bit fields — that is, bit-field members with no identifier — can be used for padding.

Note An unnamed bit field of width 0 forces alignment of the next bit field to the next type boundary, where type is the type of the member.

The following example declares a structure that contains bit fields:

struct Date
{
    unsigned nWeekDay  : 3;    // 0..7   (3 bits)
    unsigned nMonthDay : 6;    // 0..31  (6 bits)
    unsigned nMonth    : 5;    // 0..12  (5 bits)
    unsigned nYear     : 8;    // 0..100 (8 bits)
};

The conceptual memory layout of an object of type Date is shown in Figure 8.2.

Figure 8.2 Memory Layout of Date Object

Note that nYear is 8 bits long and would overflow the word boundary of the declared type, unsigned int. Therefore, it is begun at the beginning of a new unsigned int. It is not necessary that all bit fields fit in one object of the underlying type; new units of storage are allocated, according to the number of bits requested in the declaration.

Microsoft Specific

The ordering of data declared as bit fields is from low to high bit, as shown in Figure 8.2.

END Microsoft Specific

If the declaration of a structure includes an unnamed field of length 0, as shown in the following example,

struct Date
{
    unsigned nWeekDay  : 3;    // 0..7   (3 bits)
    unsigned nMonthDay : 6;    // 0..31  (6 bits)
    unsigned           : 0;    // Force alignment to next boundary.
    unsigned nMonth    : 5;    // 0..12  (5 bits)
    unsigned nYear     : 8;    // 0..100 (8 bits)
};

the memory layout is as shown in Figure 8.3.

Figure 8.3 Layout of Date Object with Zero-Length Bit Field

The underlying type of a bit field must be an integral type, as described in Fundamental Types in Chapter 2.


Restrictions on Use of Bit Fields

The following list details erroneous operations on bit fields:

  • Taking the address of a bit field

  • Initializing a reference with a bit field


Nested Class Declarations

A class can be declared within the scope of another class. Such a class is called a “nested class.” Nested classes are considered to be within the scope of the enclosing class and are available for use within that scope. To refer to a nested class from a scope other than its immediate enclosing scope, you must use a fully qualified name.

The following example shows how to declare nested classes:

class BufferedIO
{
public:
    enum IOError { None, Access, General };

    // Declare nested class BufferedInput.
    class BufferedInput
    {
    public:
        int read();
        int good() { return _inputerror == None; }
    private:
        IOError _inputerror;
    };

    // Declare nested class BufferedOutput.
    class BufferedOutput
    {
        // Member list
    };
};

BufferedIO::BufferedInput and BufferedIO::BufferedOutput are declared within BufferedIO. These class names are not visible outside the scope of class BufferedIO. However, an object of type BufferedIO does not contain any objects of types BufferedInput or BufferedOutput.

Nested classes can directly use names, type names, names of static members, and enumerators only from the enclosing class. To use names of other class members, you must use pointers, references, or object names.

In the preceding BufferedIO example, the enumeration IOError can be accessed directly by member functions in the nested classes, BufferedIO::BufferedInput or BufferedIO::BufferedOutput, as shown in function good.

Note Nested classes declare only types within class scope. They do not cause contained objects of the nested class to be created. The preceding example declares two nested classes but does not declare any objects of these class types.


Access Privileges and Nested Classes

Nesting a class within another class does not give special access privileges to member functions of the nested class. Similarly, member functions of the enclosing class have no special access to members of the nested class.

For more information about access privileges, see Chapter 10, Member-Access Control.


Member Functions in Nested Classes

Member functions declared in nested classes can be defined in file scope. The preceding example could have been written:

class BufferedIO
{
public:
    enum IOError { None, Access, General };
    class BufferedInput
    {
    public:
        int read(); // Declare but do not define member
        int good(); //  functions read and good.
    private:
        IOError _inputerror;
    };

    class BufferedOutput
    {
        // Member list.
    };
};
// Define member functions read and good in
//  file scope.
int BufferedIO::BufferedInput::read()
{
    ...
}

int BufferedIO::BufferedInput::good()
{
    return _inputerror == None;
}

In the preceding example, the qualified-type-name syntax is used to declare the function name. The declaration:

BufferedIO::BufferedInput::read()

means “the read function that is a member of the BufferedInput class that is in the scope of the BufferedIO class.” Because this declaration uses the qualified-type-name syntax, constructs of the following form are possible:

typedef BufferedIO::BufferedInput BIO_INPUT;

int BIO_INPUT::read()

The preceding declaration is equivalent to the previous one, but it uses a typedef name in place of the class names.


Friend Functions and Nested Classes

Friend functions declared in a nested class are considered to be in the scope of the nested class, not the enclosing class. Therefore, the friend functions gain no special access privileges to members or member functions of the enclosing class. If you want to use a name that is declared in a nested class in a friend function and the friend function is defined in file scope, use qualified type names as follows:

extern char *rgszMessage[];

class BufferedIO
{
public:
    ...
class BufferedInput
    {
    public:
        friend int GetExtendedErrorStatus();
        ...
        static char *message;
        int          iMsgNo;
    };
};
char *BufferedIO::BufferedInput::message;

int GetExtendedErrorStatus()
{
    ...
    strcpy( BufferedIO::BufferedInput::message,
            rgszMessage[iMsgNo] );
    return iMsgNo;
}

The preceding code shows the function GetExtendedErrorStatus declared as a friend function. In the function, which is defined in file scope, a message is copied from a static array into a class member. Note that a better implementation of GetExtendedErrorStatus is to declare it as:

int GetExtendedErrorStatus( char *message )

With the preceding interface, several classes can use the services of this function by passing a memory location where they want the error message copied.


Type Names in Class Scope

Type names defined within class scope are considered local to their class. They cannot be used outside that class. The following example demonstrates this concept:

class Tree
{
public:
   typedef Tree * PTREE;
   PTREE  Left;
   PTREE  Right;
   void  *vData;
};

PTREE pTree;  // Error: not in class scope.


Derived Classes

This chapter explains how to use derived classes to produce extensible programs.

The following topics are included:

  • Overview

  • Multiple base classes

  • Virtual functions

  • Abstract classes

  • Summary of scope rules


Overview of Derived Classes

New classes can be derived from existing classes using a mechanism called “inheritance” (see the information beginning in Single Inheritance). Classes that are used for derivation are called “base classes” of a particular derived class. A derived class is declared using the following syntax:

Syntax

base-spec :

: base-list

base-list :

base-specifier
base-list , base-specifier

base-specifier :

complete-class-name
virtual access-specifieropt complete-class-name
access-specifier virtualopt complete-class-name

access-specifier :

private
protected
public


Single Inheritance

In “single inheritance,” a common form of inheritance, classes have only one base class. Consider the relationship illustrated in Figure 9.1

Figure 9.1 Simple Single-Inheritance Graph

Note the progression from general to specific in Figure 9.1. Another common attribute found in the design of most class hierarchies is that the derived class has a “kind of” relationship with the base class. In Figure 9.1, a Book is a kind of a PrintedDocument, and a PaperbackBook is a kind of a book.

One other item of note in Figure 9.1: Book is both a derived class (from PrintedDocument) and a base class (PaperbackBook is derived from Book). A skeletal declaration of such a class hierarchy is shown in the following example:

class PrintedDocument
{
    // Member list.
};

// Book is derived from PrintedDocument.
class Book : public PrintedDocument
{
    // Member list.
};

// PaperbackBook is derived from Book.
class PaperbackBook : public Book
{
    // Member list.
};

PrintedDocument is considered a “direct base” class to Book; it is an “indirect base” class to PaperbackBook. The difference is that a direct base class appears in the base list of a class declaration and an indirect base does not.

The base class from which each class is derived is declared before the declaration of the derived class. It is not sufficient to provide a forward-referencing declaration for a base class; it must be a complete declaration.

In the preceding example, the access specifier public is used. The meaning of public, protected, and private inheritance is described in Chapter 10, Member-Access Control.

A class can serve as the base class for many specific classes, as illustrated in Figure 9.2.

Figure 9.2 Sample of Directed Acyclic Graph

In the diagram in Figure 9.2, called a “directed acyclic graph” (or “DAG”), some of the classes are base classes for more than one derived class. However, the reverse is not true: there is only one direct base class for any given derived class. The graph in Figure 9.2 depicts a “single inheritance” structure.

Note Directed acyclic graphs are not unique to single inheritance. They are also used to depict multiple-inheritance graphs. This topic is covered in Multiple Inheritance.

In inheritance, the derived class contains the members of the base class plus any new members you add. As a result, a derived class can refer to members of the base class (unless those members are redefined in the derived class). The scope-resolution operator (::) can be used to refer to members of direct or indirect base classes when those members have been redefined in the derived class. Consider this example:

class Document
{
public:
    char *Name;           // Document name.
    void  PrintNameOf();  // Print name.
};

// Implementation of PrintNameOf function from class Document.
void Document::PrintNameOf()
{
    cout << Name << endl;
}

class Book : public Document
{
public:
    Book( char *name, long pagecount );
private:
    long  PageCount;
};

// Constructor from class Book.
Book::Book( char *name, long pagecount )
{
    Name = new char[ strlen( name ) + 1 ];
    strcpy( Name, name );
    PageCount = pagecount;
};

Note that the constructor for Book, (Book::Book), has access to the data member, Name. In a program, an object of type Book can be created and used as follows:

//  Create a new object of type Book. This invokes the
//   constructor Book::Book.
Book LibraryBook( "Programming Windows, 2nd Ed", 944 );

...

//  Use PrintNameOf function inherited from class Document.
LibraryBook.PrintNameOf();

As the preceding example demonstrates, class-member and inherited data and functions are used identically. If the implementation for class Book calls for a reimplementation of the PrintNameOf function, the function that belongs to the Document class can be called only by using the scope-resolution (::) operator:

class Book : public Document
{
    Book( char *name, long pagecount );
    void PrintNameOf();
    long  PageCount;
};
void Book::PrintNameOf()
{
    cout << "Name of book: ";
    Document::PrintNameOf();
}

Pointers and references to derived classes can be implicitly converted to pointers and references to their base classes if there is an accessible, unambiguous base class. The following code demonstrates this concept using pointers (the same principle applies to references):

#include <iostream.h>

void main()
{
    Document *DocLib[10];  // Library of ten documents.

    for( int i = 0; i < 10; ++i )
    {
        cout << "Type of document: "
             << "P)aperback, M)agazine, H)elp File, C)BT"
             << endl;

        char cDocType;
        cin >> cDocType;

        switch( tolower( cDocType ) )
        {
        case 'p':
            DocLib[i] = new PaperbackBook;
            break;

        case 'm':
            DocLib[i] = new Magazine;
            break;

        case 'h':
            DocLib[i] = new HelpFile;
            break;

        case 'c':
            DocLib[i] = new ComputerBasedTraining;
            break;

        default:
            --i;
            break;
       }
    }

    for( i = 0; i < 10; ++i )
        DocLib[i]->PrintNameOf();
}

In the SWITCH statement in the preceding example, objects of different types are created, depending on what the user specified for cDocType. However, because these types are all derived from the Document class, there is an implicit conversion to Document *. As a result, DocLib is a “heterogeneous list” (a list in which not all objects are of the same type) containing different kinds of objects.

Because the Document class has a PrintNameOf function, it can print the name of each book in the library, although it may omit some of the information specific to the type of document (page count for Book, number of bytes for HelpFile, and so on).

Note Forcing the base class to implement a function such as PrintNameOf is often not the best design. Virtual Functions offers other design alternatives.


Multiple Inheritance

Later versions of C++ introduced a “multiple inheritance” model for inheritance. In a multiple-inheritance graph, the derived classes may have a number of direct base classes. Consider the graph in Figure 9.3.

Figure 9.3 Simple Multiple-Inheritance Graph

The diagram in Figure 9.3 shows a class, CollectibleString. It is like a Collectible (something that can be contained in a collection), and it is like a String. Multiple inheritance is a good solution to this kind of problem (where a derived class has attributes of more than one base class) because it is easy to form a CollectibleCustomer, CollectibleWindow, and so on.

If the properties of either class are not required for a particular application, either class can be used alone or in combination with other classes. Therefore, given the hierarchy depicted in Figure 9.3 as a basis, you can form noncollectible strings and collectibles that are not strings. This flexibility is not possible using single inheritance.


Virtual Base Class Hierarchies

Some class hierarchies are broad but have many things in common. The common code is implemented in a base class, whereas the specific code is in the derived classes.

It is important for the base classes to establish a protocol through which the derived classes can attain maximum functionality. These protocols are commonly implemented using virtual functions. Sometimes the base class provides a default implementation for such functions. In a class hierarchy such as the Document hierarchy in Figure 9.2, two useful functions are Identify and WhereIs.

When called, the Identify function returns a correct identification, appropriate to the kind of document: For a Book, a function call such as doc->Identify() must return the ISBN number; however, for a HelpFile, a product name and revision number are probably more appropriate. Similarly, WhereIs should return a row and shelf for a Book, but for a HelpFile it should return a disk location — perhaps a directory and filename.

It is important that all implementations of the Identify and WhereIs functions return the same kind of information. In this case, a character string is appropriate.

These functions are implemented as virtual functions and then invoked using a pointer to a base class. The binding to the actual code occurs at run time, selecting the correct Identify or WhereIs function.


Class Protocol Implementation

Classes can be implemented to enforce a protocol. These classes are called “abstract classes” because no object of the class type can be created. They exist solely for derivation.

Classes are abstract classes if they contain pure virtual functions or if they inherit pure virtual functions and do not provide an implementation for them. Pure virtual functions are virtual functions declared with the pure-specifier (= 0), as follows:

virtual char *Identify() = 0;

The base class, Document, might impose the following protocol on all derived classes:

  • An appropriate Identify function must be implemented.

  • An appropriate WhereIs function must be implemented.

By specifying such a protocol when designing the Document class, the class designer can be assured that no nonabstract class can be implemented without
Identify and WhereIs functions. The Document class, therefore, contains these declarations:

class Document
{
public:
    ...
    //  Requirements for derived classes: They must implement
    //   these functions.
    virtual char *Identify() = 0;
    virtual char *WhereIs() = 0;
    ...
};


Base Classes

As discussed previously, the inheritance process creates a new derived class that is made up of the members of the base class(es) plus any new members added by the derived class. In a multiple-inheritance, it is possible to construct an inheritance graph where the same base class is part of more than one of the derived classes. Figure 9.4 shows such a graph.

In Figure 9.4, pictorial representations of the components of CollectibleString and CollectibleSortable are shown. However, the base class, Collectible, is in CollectibleSortableString through the CollectibleString path and the CollectibleSortable path. To eliminate this redundancy, such classes can be declared as virtual base classes when they are inherited.

For information about declaring virtual base classes and how objects with virtual base classes are composed, see Virtual Base Classes.

Figure 9.4 Multiple Instances of a Single Base Class


Multiple Base Classes

As described in Multiple Inheritance, a class can be derived from more than one base class. In a multiple-inheritance model (where classes are derived from more than one base class), the base classes are specified using the base-list grammar element (see Syntax in Overview). For example, the class declaration for CollectionOfBook, derived from Collection and Book, can be specified:

class CollectionOfBook : public Book, public Collection
{
    // New members
};

The order in which base classes are specified is not significant except in certain cases where constructors and destructors are invoked. In these cases, the order in which base classes are specified affects the following:

  • The order in which initialization by constructor takes place. If your code relies on the Book portion of CollectionOfBook to be initialized before the Collection part, the order of specification is significant. Initialization takes place in the order the classes are specified in the base-list.

  • The order in which destructors are invoked to clean up. Again, if a particular “part” of the class must be present when the other part is being destroyed, the order is significant. Destructors are called in the reverse order of the classes specified in the base-list.

Note The order of specification of base classes can affect the memory layout of the class. Do not make any programming decisions based on the order of base members in memory.

When specifying the base-list, you cannot specify the same class name more than once. However, it is possible for a class to be an indirect base to a derived class more than once.


Virtual Base Classes

Because a class can be an indirect base class to a derived class more than once, C++ provides a way to optimize the way such base classes work. Consider the class hierarchy in Figure 9.5, which illustrates a simulated lunch line.

Figure 9.5 Simulated Lunch-Line Graph

In Figure 9.5, Queue is the base class for both CashierQueue and LunchQueue. However, when both classes are combined to form LunchCashierQueue, the following problem arises: the new class contains two subobjects of type Queue, one from CashierQueue and the other from LunchQueue. Figure 9.6 shows the conceptual memory layout (the actual memory layout might be optimized).

Figure 9.6 Simulated Lunch-Line Object

Note that there are two Queue subobjects in the LunchCashierQueue object. The following code declares Queue to be a virtual base class:

class Queue
{
    // Member list
};

class CashierQueue : virtual public Queue
{
    // Member list
};

class LunchQueue : virtual public Queue
{
    // Member list
};

class LunchCashierQueue : public LunchQueue, public CashierQueue
{
    // Member list
};

The virtual keyword ensures that only one copy of the subobject Queue is included (see Figure 9.7).

Figure 9.7 Simulated Lunch-Line Object with Virtual Base Classes

A class can have both a virtual component and a nonvirtual component of a given type. This happens in the conditions illustrated in Figure 9.8.

Figure 9.8 Virtual and Nonvirtual Components of the Same Class

In Figure 9.8., CashierQueue and LunchQueue use Queue as a virtual base class. However, TakeoutQueue specifies Queue as a base class, not a virtual base class. Therefore, LunchTakeoutCashierQueue has two subobjects of type Queue: one from the inheritance path that includes LunchCashierQueue and one from the path that includes TakeoutQueue. This is illustrated in Figure 9.9.

Figure 9.9 Object Layout with Virtual and Nonvirtual Inheritance

Note Virtual inheritance provides significant size benefits when compared with nonvirtual inheritance. However, it can introduce extra processing overhead.

If a derived class overrides a virtual function that it inherits from a virtual base class, and if a constructor or a destructor for the derived base class calls that function using a pointer to the virtual base class, the compiler may introduce additional hidden “vtordisp” fields into the classes with virtual bases. The /vd0 compiler option suppresses the addition of the hidden vtordisp constructor/destructor displacement member. The /vd1 compiler option, the default, enables them where they are necessary. Turn off vtordisps only if you are sure that all class constructors and destructors call virtual functions virtually.

The /vd compiler option affects an entire compilation module. Use the vtordisp pragma to suppress and then reenable vtordisp fields on a class-by-class basis:

#pragma vtordisp( off )
class GetReal : virtual public { ... };
#pragma vtordisp( on )


Name Ambiguities

Multiple inheritance introduces the possibility for names to be inherited along more than one path. The class-member names along these paths are not necessarily unique. These name conflicts are called “ambiguities.”

Any expression that refers to a class member must make an unambiguous reference. The following example shows how ambiguities develop:

// Declare two base classes, A and B.
class A
{
public:
    unsigned a;
    unsigned b();
};

class B
{
public:
    unsigned a();  // Note that class A also has a member "a"
    int b();       //  and a member "b".
    char c;
};

// Define class C as derived from A and B.
class C : public A, public B
{
};

Given the preceding class declarations, code such as the following is ambiguous because it is unclear whether b refers to the b in A or in B:

C *pc = new C;

pc->b();

Consider the preceding example. Because the name a is a member of both class A and class B, the compiler cannot discern which a designates the function to be called. Access to a member is ambiguous if it can refer to more than one function, object, type, or enumerator.

The compiler detects ambiguities by performing tests in this order:

  1. If access to the name is ambiguous (as just described), an error message is generated.

  2. If overloaded functions are unambiguous, they are resolved. (For more information about function overloading ambiguity, see Argument Matching in Chapter 12.)

  3. If access to the name violates member-access permission, an error message is generated. (For more information, see Chapter 10, Member-Access Control.)

When an expression produces an ambiguity through inheritance, you can manually resolve it by qualifying the name in question with its class name. To make the preceding example compile properly with no ambiguities, use code such as:

C *pc = new C;

pc->B::a();

Note When C is declared, it has the potential to cause errors when B is referenced in the scope of C. No error is issued, however, until an unqualified reference to B is actually made in C’s scope.


Ambiguities and Virtual Base Classes

If virtual base classes are used, functions, objects, types, and enumerators can be reached through multiple-inheritance paths. Because there is only one instance of the base class, there is no ambiguity when accessing these names.

Figure 9.10 shows how objects are composed using virtual and nonvirtual inheritance.

Figure 9.10 Virtual vs. Nonvirtual Derivation

In Figure 9.10, accessing any member of class A through nonvirtual base classes causes an ambiguity; the compiler has no information that explains whether to use the subobject associated with B or the subobject associated with C. However, when A is specified as a virtual base class, there is no question which subobject is being accessed.


Dominance

It is possible for more than one name (function, object, or enumerator) to be reached through an inheritance graph. Such cases are considered ambiguous with nonvirtual base classes. They are also ambiguous with virtual base classes, unless one of the names “dominates” the others.

A name dominates another name if it is defined in both classes and one class is derived from the other. The dominant name is the name in the derived class; this name is used when an ambiguity would otherwise have arisen, as shown in the following example:

class A
{
public:
    int a;
};

class B : public virtual A
{
public:
    int a();
};

class C : public virtual A
{
   ...
};

class D : public B, public C
{
public:
    D() { a(); } // Not ambiguous. B::a() dominates A::a.
};


Ambiguous Conversions

Explicit and implicit conversions from pointers or references to class types can cause ambiguities. Figure 9.11 shows the following:

  • The declaration of an object of type D.

  • The effect of applying the address-of operator (&) to that object. Note that the address-of operator always supplies the base address of the object.

  • The effect of explicitly converting the pointer obtained using the address-of operator to the base-class type A. Note that coercing the address of the object to type A* does not always provide the compiler with enough information as to which subobject of type A to select; in this case, two subobjects exist.

The conversion to type A* (pointer to A) is ambiguous because there is no way to discern which subobject of type A is the correct one. Note that you can avoid the ambiguity by explicitly specifying which subobject you mean to use, as follows:

(A *)(B *)&d       // Use B subobject.
(A *)(C *)&d       // Use C subobject.

Figure 9.11 Ambiguous Conversion of Pointers to Base Classes


Virtual Functions

“Virtual functions” are functions that ensure that the correct function is called for an object, regardless of the expression used to make the function call.

Suppose a base class contains a function declared as virtual and a derived class defines the same function. The function from the derived class is invoked for objects of the derived class, even if it is called using a pointer or reference to the base class. The following example shows a base class that provides an implementation of the PrintBalance function:

class Account
{
public:
                   Account( double d );  // Constructor.
    virtual double GetBalance();         // Obtain balance.
    virtual void   PrintBalance();       // Default implementation.
private:
    double _balance;
};

// Implementation of constructor for Account.
double Account::Account( double d )
{
    _balance = d;
}
// Implementation of GetBalance for Account.
double Account::GetBalance()
{
    return _balance;
}
// Default implementation of PrintBalance.
void Account::PrintBalance()
{
    cerr << "Error. Balance not available for base type."
         << endl;
}

Two derived classes, CheckingAccount and SavingsAccount, can be created as follows:

class CheckingAccount : public Account
{
public:
    void PrintBalance();
};

// Implementation of PrintBalance for CheckingAccount.
void CheckingAccount::PrintBalance()
{
    cout << "Checking account balance: " << GetBalance();
}

class SavingsAccount : public Account
{
public:
    void PrintBalance();
};

// Implementation of PrintBalance for SavingsAccount.
void SavingsAccount::PrintBalance()
{
    cout << "Savings account balance: " << GetBalance();
}

The PrintBalance function in the derived classes is virtual because it is declared as virtual in the base class, Account. To call virtual functions such as PrintBalance, code such as the following can be used:

// Create objects of type CheckingAccount and SavingsAccount.
CheckingAccount *pChecking = new CheckingAccount( 100.00 );
SavingsAccount  *pSavings  = new SavingsAccount( 1000.00 );

// Call PrintBalance using a pointer to Account.
Account *pAccount = pChecking;
pAccount->PrintBalance();

// Call PrintBalance using a pointer to Account.
pAccount = pSavings;
pAccount->PrintBalance();

In the preceding code, the calls to PrintBalance are identical, except for the object pAccount points to. Because PrintBalance is virtual, the version of the function defined for each object is called. The PrintBalance function in the derived classes CheckingAccount and SavingsAccount “override” the function in the base class Account.

If a class is declared that does not provide an overriding implementation of the PrintBalance function, the default implementation from the base class Account is used.

Functions in derived classes override virtual functions in base classes only if their type is the same. A function in a derived class cannot differ from a virtual function in a base class in its return type only; the argument list must differ as well.

When calling a function using pointers or references, the following rules apply:

  • A call to a virtual function is resolved according to the underlying type of object for which it is called.

  • A call to a nonvirtual function is resolved according to the type of the pointer or reference.

The following example shows how virtual and nonvirtual functions behave when called through pointers:

#include <iostream.h>

// Declare a base class.
class Base
{
public:
    virtual void NameOf();          // Virtual function.
            void InvokingClass();   // Nonvirtual function.
};

// Implement the two functions.
void Base::NameOf()
{
    cout << "Base::NameOf\n";
}

void Base::InvokingClass()
{
    cout << "Invoked by Base\n";
}

// Declare a derived class.
class Derived : public Base
{
public:
    void NameOf();          // Virtual function.
    void InvokingClass();   // Nonvirtual function.
};

// Implement the two functions.
void Derived::NameOf()
{
    cout << "Derived::NameOf\n";
}

void Derived::InvokingClass()
{
    cout << "Invoked by Derived\n";
}

void main()
{
    // Declare an object of type Derived.
    Derived aDerived;
    // Declare two pointers, one of type Derived * and the other
    //  of type Base *, and initialize them to point to aDerived.
    Derived *pDerived = &aDerived;
    Base    *pBase    = &aDerived;
    // Call the functions.
    pBase->NameOf();           // Call virtual function.
    pBase->InvokingClass();    // Call nonvirtual function.
    pDerived->NameOf();        // Call virtual function.
    pDerived->InvokingClass(); // Call nonvirtual function.
}

The output from this program is:

Derived::NameOf
Invoked by Base
Derived::NameOf
Invoked by Derived

Note that regardless of whether the NameOf function is invoked through a pointer to Base or a pointer to Derived, it calls the function for Derived. It calls the function for Derived because NameOf is a virtual function, and both pBase and pDerived point to an object of type Derived.

Because virtual functions are called only for objects of class types, you cannot declare global or static functions as virtual.

The virtual keyword can be used when declaring overriding functions in a derived class, but it is unnecessary; overrides of virtual functions are always virtual.

Virtual functions in a base class must be defined unless they are declared using the pure-specifier. (For more information about pure virtual functions, see Abstract Classes.)

The virtual function-call mechanism can be suppressed by explicitly qualifying the function name using the scope-resolution operator (::). Consider the preceding example. To call PrintBalance in the base class, use code such as the following:

CheckingAccount *pChecking = new CheckingAccount( 100.00 );

pChecking->Account::PrintBalance();  //  Explicit qualification.

Account *pAccount = pChecking;  // Call Account::PrintBalance

pAccount->Account::PrintBalance();   //  Explicit qualification.

Both calls to PrintBalance in the preceding example suppress the virtual function-call mechanism.


Abstract Classes

Abstract classes act as expressions of general concepts from which more specific classes can be derived. You cannot create an object of an abstract class type; however, you can use pointers and references to abstract class types.

A class that contains at least one pure virtual function is considered an abstract class. Classes derived from the abstract class must implement the pure virtual function or they, too, are abstract classes.

A virtual function is declared as “pure” by using the pure-specifier syntax (described in Class Protocol Implementation). Consider the example presented in Virtual Functions. The intent of class Account is to provide general functionality, but objects of type Account are too general to be useful. Therefore, Account is a good candidate for an abstract class:

class Account
{
public:
                   Account( double d );  // Constructor.
    virtual double GetBalance();         // Obtain balance.
    virtual void   PrintBalance() = 0;   // Pure virtual function.
private:
    double _balance;
};

The only difference between this declaration and the previous one is that PrintBalance is declared with the pure specifier (= 0).


Restrictions on Using Abstract Classes

Abstract classes cannot be used for:

  • Variables or member data

  • Argument types

  • Function return types

  • Types of explicit conversions

Another restriction is that if the constructor for an abstract class calls a pure virtual function, either directly or indirectly, the result is undefined. However, constructors and destructors for abstract classes can call other member functions.

Pure virtual functions can be defined for abstract classes, but they can be called directly only by using the syntax:

abstract-class-name :: function-name( )

This helps when designing class hierarchies whose base class(es) include pure virtual destructors, because base class destructors are always called in the process of destroying an object. Consider the following example:

#include <iostream.h>

// Declare an abstract base class with a pure virtual destructor.
class base
{
public:
    base() {}
    virtual ~base()=0;
};

// Provide a definition for destructor.
base::~base()
{
}

class derived:public base
{
public:
    derived() {}
    ~derived(){}
};

void main()
{
    derived *pDerived = new derived;

    delete pDerived;
}

When the object pointed to by pDerived is deleted, the destructor for class derived is called and then the destructor for class base is called. The empty implementation for the pure virtual function ensures that at least some implementation exists for the function.

Note In the preceding example, the pure virtual function base::~base is called implicitly from derived::~derived. It is also possible to call pure virtual functions explicitly using a fully qualified member-function name.


Summary of Scope Rules

This section supplements Scope by adding the concepts pertaining to classes. The following topics are included:

  • Ambiguity

  • Global names

  • Names and qualified names

  • Function argument names

  • Constructor initializers


Ambiguity

The use of a name must be unambiguous within its scope (up to the point where overloading is determined). If the name denotes a function, the function must be unambiguous with respect to number and type of arguments. If the name remains unambiguous, member-access rules are applied.


Global Names

A name of an object, function, or enumerator is global if it is introduced outside any function or class or prefixed by the global unary scope operator (::), and if it is not used in conjunction with any of these binary operators:

  • Scope-resolution (::)

  • Member-selection for objects and references (.)

  • Member-selection for pointers (–>)


Names and Qualified Names

Names used with the binary scope-resolution operator (::) are called “qualified names.” The name specified after the binary scope-resolution operator must be a member of the class specified on the left of the operator or a member of its base class(es).

Names specified after the member-selection operator (. or –>) must be members of the class type of the object specified on the left of the operator or members of its base class(es). Names specified on the right of the member-selection operator (–>) can also be objects of another class type, provided that the left-hand side of –> is a class object and that the class defines an overloaded member-selection operator (–>) that evaluates to a pointer to some other class type. (This provision is discussed in more detail in Class Member Access in Chapter 12.)

The compiler searches for names in the following order, stopping when the name is found:

  1. Current block scope if name is used inside a function; otherwise, global scope.

  2. Outward through each enclosing block scope, including the outermost function scope (which includes function arguments).

  3. If the name is used inside a member function, the class’s scope is searched for the name.

  4. The class’s base classes are searched for the name.

  5. The enclosing nested class scope (if any) and its bases are searched. The search continues until the outermost enclosing class scope is searched.

  6. Global scope is searched.

However, you can make modifications to this search order as follows:

  7. Names preceded by :: force the search to begin at global scope.

  8. Names preceded by the class, struct, and union keywords force the compiler to search only for class, struct, or union names.

  9. Names on the left side of the scope-resolution operator (::) can be only class, struct, or union names.

If the name refers to a nonstatic member but is used in a static member function, an error message is generated. Similarly, if the name refers to any nonstatic member in an enclosing class, an error message is generated because enclosed classes do not have enclosing-class this pointers.


Function Argument Names

Function argument names in function definitions are considered to be in the scope of the outermost block of the function. Therefore, they are local names and go out of scope when the function is exited.

Function argument names in function declarations (prototypes) are in local scope of the declaration and go out of scope at the end of the declaration.

Default arguments are in the scope of the argument for which they are the default, as described in the preceding two paragraphs. However, they cannot access local variables or nonstatic class members. Default arguments are evaluated at the point of the function call, but they are evaluated in the function declaration’s original scope. Therefore, the default arguments for member functions are always evaluated in class scope.


Constructor Initializers

Constructor initializers (described in Initializing Bases and Members in Chapter 11) are evaluated in the scope of the outermost block of the constructor for which they are specified. Therefore, they can use the constructor’s argument names.


Member-Access Control

With C++, you can specify the level of access to member data and functions. There are three levels of access: public, protected, and private. This chapter explains how access control applies to objects of class type and to derived classes. This chapter includes the following topics:

  • Controlling access to class members

  • Access specifiers

  • Access specifiers for base classes

  • Friends

  • Protected member access

  • Access to virtual functions

  • Multiple access


Controlling Access to Class Members

You can increase the integrity of software built with C++ by controlling access to class member data and functions. Class members can be declared as having private, protected, or public access, as shown in Table 10.1.

Table 10.1 Member-Access Control

Type of Access | Meaning
private | Class members declared as private can be used only by member functions and friends (classes or functions) of the class.
protected | Class members declared as protected can be used by member functions and friends (classes or functions) of the class. Additionally, they can be used by classes derived from the class.
public | Class members declared as public can be used by any function.

Access control prevents you from using objects in ways they were not intended to be used. This protection is lost when explicit type conversions (casts) are performed.

Note Access control is equally applicable to all names: member functions, member data, nested classes, and enumerators.

The default access to class members (members of a class type declared using the class keyword) is private; the default access to struct and union members is public. For either case, the current access level can be changed using the public, private, or protected keyword.


Access Specifiers

In class declarations, members can have access specifiers.

Syntax

access-specifier : member-listopt

The access-specifier determines the access to the names that follow it, up to the next access-specifier or the end of the class declaration. Figure 10.1 illustrates this concept.

Figure 10.1 Access Control in Classes

Although only two access specifiers are shown in Figure 10.1, there is no limit to the number of access specifiers in a given class declaration. For example, the Point class in Figure 10.1 could just as easily be declared using multiple access specifiers as follows:

class Point
{
public:                  // Declare public constructor.
    Point( int, int );
private:                 // Declare private state variable.
    int _x;
public:                  // Declare public constructor.
    Point();
public:                  // Declare public accessor.
    int &x( int );
private:                 // Declare private state variable.
    int _y;
public:                  // Declare public accessor.
    int &y( int );
};

Note that there is no specific order required for member access, as shown in the preceding example. The allocation of storage for objects of class types is implementation dependent, but members are guaranteed to be assigned successively higher memory addresses between access specifiers.


Access Specifiers for Base Classes

Two factors control which members of a base class are accessible in a derived class; these same factors control access to the inherited members in the derived class:

  • Whether the derived class declares the base class using the public access specifier in the class-head (class-head is described in Syntax in Defining Class Types in Chapter 8).

  • What the access to the member is in the base class.

Table 10.2 shows the interaction between these factors and how to determine base-class member access.

Table 10.2 Member Access in Base Class

private | protected | public
Always inaccessible regardless of derivation access | Private in derived class if you use private derivation | Private in derived class if you use private derivation
 | Protected in derived class if you use protected derivation | Protected in derived class if you use protected derivation
 | Protected in derived class if you use public derivation | Public in derived class if you use public derivation

The following example illustrates this:

class BaseClass
{
public:
    int PublicFunc();    // Declare a public member.
protected:
    int ProtectedFunc(); // Declare a protected member.
private:
    int PrivateFunc();   // Declare a private member.
};

// Declare two classes derived from BaseClass.
class DerivedClass1 : public BaseClass
{ };

class DerivedClass2 : private BaseClass
{ };

In DerivedClass1, the member function PublicFunc is a public member and ProtectedFunc is a protected member because BaseClass is a public base class. PrivateFunc is private to BaseClass, and it is inaccessible to any derived classes.

In DerivedClass2, the functions PublicFunc and ProtectedFunc are considered private members because BaseClass is a private base class. Again, PrivateFunc is private to BaseClass, and it is inaccessible to any derived classes.

You can declare a derived class without a base-class access specifier. In such a case, the derivation is considered private if the derived class declaration uses the class keyword. The derivation is considered public if the derived class declaration uses the struct keyword. For example, the following code:

class Derived : Base
...

is equivalent to:

class Derived : private Base
...

Similarly, the following code:

struct Derived : Base
...

is equivalent to:

struct Derived : public Base
...

Note that members declared as having private access are not accessible to functions or derived classes unless those functions or classes are declared using the friend declaration in the base class.

A union type cannot have a base class.

Note When specifying a private base class, it is advisable to explicitly use the private keyword so users of the derived class understand the member access.


Access Control and Static Members

When you specify a base class as private, it affects only nonstatic members. Public static members are still accessible in the derived classes. However, accessing members of the base class using pointers, references, or objects can require a conversion, at which time access control is again applied. Consider the following example:

class Base
{
public:
    int Print();             // Nonstatic member.
    static int CountOf();    // Static member.
};

// Derived1 declares Base as a private base class.
class Derived1 : private Base
{
};
// Derived2 declares Derived1 as a public base class.
class Derived2 : public Derived1
{
    int ShowCount();    // Nonstatic member.
};
// Define ShowCount function for Derived2.
int Derived2::ShowCount()
{
   // Call static member function CountOf explicitly.
    int cCount = Base::CountOf();     // OK.

   // Call static member function CountOf using pointer.
    cCount = this->CountOf();  // Error. Conversion of
                               //  Derived2 * to Base * not
                               //  permitted.
    return cCount;
}

In the preceding code, access control prohibits conversion from a pointer to Derived2 to a pointer to Base. The this pointer is implicitly of type Derived2 *. To select the CountOf function, this must be converted to type Base *. Such a conversion is not permitted because Base is a private indirect base class to Derived2. Conversion to a private base class type is acceptable only for pointers to immediate derived classes. Therefore, pointers of type Derived1 * can be converted to type Base *.

Note that calling the CountOf function explicitly, without using a pointer, reference, or object to select it, implies no conversion. Therefore, the call is allowed.

Members and friends of a derived class, T, can convert a pointer to T to a pointer to a private direct base class of T.


Friends

In some circumstances, it is more convenient to grant member-level access to functions that are not members of a class or to all functions in a separate class. With the friend keyword, programmers can designate either the specific functions or the classes whose functions can access not only public members but also protected and private members.


Friend Functions

Friend functions are not considered class members; they are normal external functions that are given special access privileges. Friends are not in the class’s scope, and they are not called using the member-selection operators (. and –>) unless they are members of another class. The following example shows a Point class and an overloaded operator, operator+. (This example primarily illustrates friends, not overloaded operators. For more information about overloaded operators, see Overloaded Operators in Chapter 12.)

#include <iostream.h>

// Declare class Point.
class Point
{
public:
    // Constructors
    Point() { _x = _y = 0; }
    Point( unsigned x, unsigned y ) { _x = x; _y = y; }
    // Accessors
    unsigned x() { return _x; }
    unsigned y() { return _y; }
    void     Print() { cout << "Point(" << _x << ", " << _y << ")"
                            << endl; }

    // Friend function declarations
    friend Point operator+( Point& pt, int nOffset );
    friend Point operator+( int nOffset, Point& pt );

private:
    unsigned _x;
    unsigned _y;
};

// Friend-function definitions
//
// Handle Point + int expression.
Point operator+( Point& pt, int nOffset )
{
    Point ptTemp = pt;
    // Change private members _x and _y directly.
    ptTemp._x += nOffset;
    ptTemp._y += nOffset;

    return ptTemp;
}

// Handle int + Point expression.
Point operator+( int nOffset, Point& pt )
{
    Point ptTemp = pt;
    // Change private members _x and _y directly.
    ptTemp._x += nOffset;
    ptTemp._y += nOffset;

    return ptTemp;
}

// Test overloaded operator.
void main()
{
    Point pt( 10, 20 );
    pt.Print();

    pt = pt + 3;     // Point + int
    pt.Print();

    pt = 3 + pt;     // int + Point
    pt.Print();
}

When the expression pt + 3 is encountered in the main function, the compiler determines whether an appropriate user-defined operator+ exists. In this case, the function operator+( Point pt, int nOffset ) matches the operands, and a call to the function is issued. In the second case (the expression 3 + pt), the function operator+( Point pt, int nOffset ) matches the supplied operands. Therefore, supplying these two forms of operator+ preserves the commutative properties of the + operator.

A user-defined operator+ can be written as a member function, but it takes only one explicit argument: the value to be added to the object. As a result, the commutative properties of addition cannot be correctly implemented with member functions; they must use friend functions instead.

Notice that both versions of the overloaded operator+ function are declared as friends in class Point. Both declarations are necessary — when friend declarations name overloaded functions or operators, only the particular functions specified by the argument types become friends. Suppose a third operator+ function were declared as follows:

Point &operator+( Point &pt, Point &pt );

The operator+ function in the preceding example is not a friend of class Point, simply because it has the same name as two other functions that are declared as friends.

Because friend declarations are unaffected by access specifiers, they can be declared in any section of the class declaration.


Class Member Functions and Classes as Friends

Class member functions can be declared as friends in other classes. Consider the following example:

class B;
class A
{
    int Func1( B& b ) ;
    int Func2( B& b ) ;
};

class B
{
private:
    int _b;
    friend int A::Func1( B& );   //  Grant friend access to one
                                //   function in class B.
};
 int A::Func1( B& b ) { return b._b; } //  OK: this is a friend.
 int A::Func2( B& b ) { return b._b; } //  Error: _b is a private member.

In the preceding example, only the function A::Func1( B& ) is granted friend access to class B. Therefore, access to the private member _b is correct in Func1 of class A but not in Func2.

Suppose the friend declaration in class B had been:

friend class A;

In that case, all member functions in class A would have been granted friend access to class B. Note that “friendship” cannot be inherited, nor is there any “friend of a friend” access. Figure 10.2 shows four class declarations: Base, Derived, aFriend, and anotherFriend. Only class aFriend has direct access to the private members of Base (and to any members Base might have inherited).

Figure 10.2 Implications of friend Relationship


Friend Declarations

If you declare a friend function that was not previously declared, that function is exported to the enclosing nonclass scope.

Functions declared in a friend declaration are treated as if they had been declared using the extern keyword. (For more information about extern, see Static Storage-Class Specifiers in Chapter 6.)

Although functions with global scope can be declared as friends prior to their prototypes, member functions cannot be declared as friends before the appearance of their complete class declaration. The following code shows why this fails:

class ForwardDeclared;   // Class name is known.

class HasFriends
{
    friend int ForwardDeclared::IsAFriend();   // Error.
};

The preceding example enters the class name ForwardDeclared into scope, but the complete declaration — specifically, the portion that declares the function IsAFriend — is not known. Therefore, the friend declaration in class HasFriends generates an error.

To declare two classes that are friends of one another, the entire second class must be specified as a friend of the first class. The reason for this restriction is that the compiler has enough information to declare individual friend functions only at the point where the second class is declared.

Note Although the entire second class must be a friend to the first class, you can select which functions in the first class will be friends of the second class.


Defining Friend Functions in Class Declarations

Friend functions can be defined inside class declarations. These functions are inline functions, and like member inline functions they behave as though they were defined immediately after all class members have been seen but before the class scope is closed (the end of the class declaration).

Friend functions defined inside class declarations are not considered in the scope of the enclosing class; they are in file scope.


Protected Member Access

Class members declared as protected can be used only by the following:

  • Member functions of the class that originally declared these members.

  • Friends of the class that originally declared these members.

  • Classes derived with public or protected access from the class that originally declared these members.

  • Direct privately derived classes that also have private access to protected members.

Protected members are not as private as private members, which are accessible only to members of the class in which they are declared, but they are not as public as public members, which are accessible in any function.

Protected members that are also declared as static are accessible to any friend or member function of a derived class. Protected members that are not declared as static are accessible to friends and member functions in a derived class only through a pointer to, reference to, or object of the derived class.


Access to Virtual Functions

The access control applied to virtual functions is determined by the type used to make the function call. Overriding declarations of the function do not affect the access control for a given type. For example:

class VFuncBase
{
public:
    virtual int GetState() { return _state; }
protected:
    int _state;
};

class VFuncDerived : public VFuncBase
{
private:
    int GetState() { return _state; }
};

...

VFuncDerived vfd;             // Object of derived type.
VFuncBase *pvfb = &vfd;       // Pointer to base type.
VFuncDerived *pvfd = &vfd;    // Pointer to derived type.
int State;

State = pvfb->GetState();     // GetState is public.
State = pvfd->GetState();     // GetState is private; error.

In the preceding example, calling the virtual function GetState using a pointer to type VFuncBase calls VFuncDerived::GetState, and GetState is treated as public. However, calling GetState using a pointer to type VFuncDerived is an access-control violation because GetState is declared private in class VFuncDerived.

! WARNING The virtual function GetState can be called using a pointer to the base class VFuncBase. This does not mean that the function called is the base-class version of that function.


Multiple Access

In multiple-inheritance lattices involving virtual base classes, a given name can be reached through more than one path. Because different access control can be applied along these different paths, the compiler chooses the path that gives the most access. See Figure 10.3.

Figure 10.3 Access Along Paths of an Inheritance Graph

In Figure 10.3, a name declared in class VBase is always reached through class RightPath. The right path is more accessible because RightPath declares VBase as a public base class, whereas LeftPath declares VBase as private.


Special Member Functions

C++ defines several kinds of functions that can be declared only as class members — these are called “special member functions.” These functions affect the way objects of a given class are created, destroyed, copied, and converted into objects of other types. Another important property of many of these functions is that they can be called implicitly (by the compiler).

The special member functions are described briefly in the following list:

  • Constructors. These functions enable automatic initialization of objects.

  • Destructors. These functions perform cleanup after objects are explicitly or implicitly destroyed.

  • Conversion Functions. These are used to convert between class types and other types.

  • The new operator. This is used to dynamically allocate storage.

  • The delete operator. This is used to release storage allocated using the new operator.

  • The assignment operator (operator=). This operator is used when an assignment takes place.

All of the items in the preceding list can be user-defined for each class.

Special member functions obey the same access rules as other member functions. The access rules are described in Chapter 10, Member-Access Control. Table 11.1 summarizes how member and friend functions behave.

Table 11.1 Summary of Function Behavior

Function Type | Is Function Inherited from Base Class? | Can Function Be Virtual? | Can Function Return a Value? | Is Function a Member or Friend? | Will Compiler Generate Function if User Does Not?
Constructor | No | No | No | Member | Yes
Copy Constructor | No | No | No | Member | Yes
Destructor | No | Yes | No | Member | Yes
Conversion | Yes | Yes | No | Member | No
Assignment (operator=) | No | Yes | Yes | Member | Yes
new | Yes | No | void* | Static member | No
delete | Yes | No | void | Static member | No
Other member functions | Yes | Yes | Yes | Member | No
Friend functions | No | No | Yes | Friend | No


Constructors

A member function with the same name as its class is a constructor function. Constructors cannot return values, even if they have return statements. Specifying a constructor with a return type is an error, as is taking the address of a constructor.

If a class has a constructor, each object of that type is initialized with the constructor prior to use in a program. (For more information about initialization, see Initialization Using Special Member Functions.)

Constructors are called at the point an object is created. Objects are created as:

  • Global (file-scoped or externally linked) objects.

  • Local objects, within a function or smaller enclosing block.

  • Dynamic objects, using the new operator. The new operator allocates an object on the program heap or “free store.”

  • Temporary objects created by explicitly calling a constructor. (For more information, see Temporary Objects.)

  • Temporary objects created implicitly by the compiler. (For more information, see Temporary Objects.)

  • Data members of another class. Creating objects of class type, where the class type is composed of other class-type variables, causes each object in the class to be created.

  • Base class subobject of a class. Creating objects of derived class type causes the base class components to be created.


What a Constructor Does

A constructor performs various tasks that are not visible to you as the programmer, even if you write no code for the constructor. These tasks are all associated with building a complete and correct instance of class type.

In Microsoft C++ (and some other implementations of C++), a constructor:

  • Initializes the object’s virtual base pointer(s) (vbptr). This step is performed if the class is derived from virtual base classes.

  • Calls base class and member constructors in the order of declaration.

  • Initializes the object’s virtual function pointers (vfptr). This step is performed if the class has or inherits virtual functions. Virtual function pointers point to the class’s virtual function table (v-table) and allow correct binding of virtual function calls to code.

  • Executes optional code in the body of the constructor function.

When the constructor is finished, the allocated memory is an object of a given class type. Because of the steps the constructor performs, “late binding” in the form of virtual functions can be resolved at the point of a virtual function call. The constructor has also constructed base classes and has constructed composed objects (objects included as data members). Late binding is the mechanism by which C++ implements polymorphic behavior for objects.


Rules for Declaring Constructors

A constructor has the same name as its class. Any number of constructors can be declared, subject to the rules of overloaded functions. (For more information, see Chapter 12, Overloading.)

Syntax

class-name ( argument-declaration-listopt ) cv-mod-listopt

C++ defines two special kinds of constructors, default and copy constructors, described in Table 11.2.

Table 11.2 Default and Copy Constructors

Kind of Construction | Arguments | Purpose
Default constructor | Can be called with no arguments | Construct a default object of the class type
Copy constructor | Can accept a single argument of reference to same class type | Copy objects of the class type

Default constructors can be called with no arguments. However, you can declare a default constructor with an argument list, provided all arguments have defaults. Similarly, copy constructors must accept a single argument of reference to the same class type. More arguments can be supplied, provided all subsequent arguments have defaults.

If you do not supply any constructors, the compiler attempts to generate a default constructor. If you do not supply a copy constructor, the compiler attempts to generate one. These compiler-generated constructors are considered public member functions. An error is generated if you specify a copy constructor with a first argument that is an object and not a reference.

A compiler-generated default constructor sets up the object (initializes vftables and vbtables, as described previously), and it calls the default constructors for base classes and members, but it takes no other action. Base class and member constructors are called only if they exist, are accessible, and are unambiguous.

A compiler-generated copy constructor sets up a new object and performs a memberwise copy of the contents of the object to be copied. If base class or member constructors exist, they are called; otherwise, bitwise copying is performed.

If all base and member classes of a class type have copy constructors that accept a const argument, the compiler-generated copy constructor accepts a single argument of type const type&. Otherwise, the compiler-generated copy constructor accepts a single argument of type type&.

You can use a constructor to initialize a const or volatile object, but the constructor itself cannot be declared as const or volatile. The only legal storage class for a constructor is inline; use of any other storage-class modifier, including the __declspec keyword, with a constructor causes a compiler error. Constructors and destructors cannot specify a calling convention other than __stdcall.

Constructors of base classes are not inherited by derived classes. When an object of derived class type is created, it is constructed starting with the base class components; then it moves to the derived class components. The compiler uses each base class’s constructor as that part of the complete object is initialized (except in cases of virtual derivation, as described in Initializing Base Classes).


Explicitly Called Constructors

Constructors can be explicitly called in a program to create objects of a given type. For example, to create two Point objects that describe the ends of a line, the following code can be written:

DrawLine( Point( 13, 22 ), Point( 87, 91 ) );

Two objects of type Point are created, passed to the function DrawLine, and destroyed at the end of the expression (the function call).

Another context in which a constructor is explicitly called is in an initialization:

Point pt = Point( 7, 11 );

An object of type Point is created and initialized using the constructor that accepts two arguments of type int.

Objects that are created by calling constructors explicitly, as in the preceding two examples, are unnamed and have a lifetime of the expression in which they are created. This is discussed in greater detail in Temporary Objects.


Calling Member Functions and Virtual Functions from Within Constructors

It is usually safe to call any member function from within a constructor because the object has been completely set up (virtual tables have been initialized and so on) prior to the execution of the first line of user code. However, it is potentially unsafe for a member function to call a virtual member function for an abstract base class during construction or destruction.

Constructors can call virtual functions. When virtual functions are called, the function invoked is the function defined for the constructor’s own class (or inherited from its bases). The following example shows what happens when a virtual function is called from within a constructor:

#include <iostream.h>

class Base
{
public:
    Base();             // Default constructor.
    virtual void f();   // Virtual member function.
};

Base::Base()
{
    cout << "Constructing Base sub-object\n";
    f();                // Call virtual member function
}                       //  from inside constructor.

void Base::f()
{
    cout << "Called Base::f()\n";
}

class Derived : public Base
{
public:
    Derived();          // Default constructor.
    void f();           // Implementation of virtual
};                      //  function f for this class.

Derived::Derived()
{
    cout << "Constructing Derived object\n";
}

void Derived::f()
{
    cout << "Called Derived::f()\n";
}

void main()
{
    Derived d;
}

When the preceding program is run, the declaration Derived d causes the following sequence of events:

  1. The constructor for class Derived (Derived::Derived) is called.

  2. Prior to entering the body of the Derived class’s constructor, the constructor for class Base (Base::Base) is called.

  3. Base::Base calls the function f, which is a virtual function. Ordinarily, Derived::f would be called because the object d is of type Derived. Because the Base::Base function is a constructor, the object is not yet of the Derived type, and Base::f is called.


Constructors and Arrays

Arrays are constructed only using the default constructor. Default constructors are constructors that either accept no arguments or for which all arguments have a default. Arrays are always constructed in ascending order. The initialization for each member of the array is done using the same constructor.


Order of Construction

For derived classes and classes that have class-type member data, the order in which construction occurs helps you understand what portions of the object you can use in any given constructor.


Construction and Inheritance

An object of derived type is constructed from the base class to the derived class by calling the constructors for each class in order. Each class’s constructor can rely on its base classes being completely constructed.

For a complete description of initialization, including the order of initialization, see Initializing Bases and Members.


Construction and Composed Classes

Classes that contain class-type data members are called “composed classes.” When an object of a composed class type is created, the constructors for the contained classes are called before the class’s own constructor.

For a more information about this kind of initialization, see Initializing Bases and Members.


Destructors

“Destructor” functions are the inverse of constructor functions. They are called when objects are destroyed (deallocated). Designate a function as a class’s destructor by preceding the class name with a tilde (~). For example, the destructor for class String is declared: ~String().

The destructor is commonly used to “clean up” when an object is no longer necessary. Consider the following declaration of a String class:

#include <string.h>

class String
{
public:
    String( char *ch );  // Declare constructor
    ~String();           //  and destructor.
private:
    char *_text;
};

// Define the constructor.
String::String( char *ch )
{
    // Dynamically allocate the correct amount of memory.
    _text = new char[strlen( ch ) + 1];

    // If the allocation succeeds, copy the initialization string.
    if( _text )
       strcpy( _text, ch );
}

// Define the destructor.
String::~String()
{
    // Deallocate the memory that was previously reserved
    //  for this string.
    delete[] _text;
}

In the preceding example, the destructor String::~String uses the delete operator to deallocate the space dynamically allocated for text storage.


Declaring Destructors

Destructors are functions with the same name as the class but preceded by a tilde (~).

Syntax

~class-name()

or

class-name :: ~class-name()

The first form of the syntax is used for destructors declared or defined inside a class declaration; the second form is used for destructors defined outside a class declaration.

Several rules govern the declaration of destructors. Destructors:

  • Do not accept arguments.

  • Cannot specify any return type (including void).

  • Cannot return a value using the return statement.

  • Cannot be declared as const, volatile, or static. However, they can be invoked for the destruction of objects declared as const, volatile, or static.

  • Can be declared as virtual. Using virtual destructors, you can destroy objects without knowing their type — the correct destructor for the object is invoked using the virtual function mechanism. Note that destructors can also be declared as pure virtual functions for abstract classes.


Using Destructors

Destructors are called when one of the following events occurs:

  • An object allocated using the new operator is explicitly deallocated using the delete operator. When objects are deallocated using the delete operator, memory is freed for the “most derived object,” or the object that is a complete object and not a subobject representing a base class. This “most-derived object” deallocation is guaranteed to work only with virtual destructors. Deallocation may fail in multiple-inheritance situations where the type information does not correspond to the underlying type of the actual object.

  • A local (automatic) object with block scope goes out of scope.

  • The lifetime of a temporary object ends.

  • A program ends and global or static objects exist.

  • The destructor is explicitly called using the destructor function’s fully qualified name. (For more information, see Explicit Destructor Calls.)

The cases described in the preceding list ensure that all objects can be destroyed with user-defined methods.

If a base class or data member has an accessible destructor, and if a derived class does not declare a destructor, the compiler generates one. This compiler-generated destructor calls the base class destructor and the destructors for members of the derived type. Default destructors are public. (For more information about accessibility, see Access Specifiers for Base Classes in Chapter 10.)

Destructors can freely call class member functions and access class member data. When a virtual function is called from a destructor, the function called is the function for the class currently being destroyed. (For more information, see Order of Destruction.)

There are two restrictions on the use of destructors. The first restriction is that you cannot take the address of a destructor. The second is that derived classes do not inherit their base class’s destructors. Instead, as previously explained, they always override the base class’s destructors.


Order of Destruction

When an object goes out of scope or is deleted, the sequence of events in its complete destruction is as follows:

  1. The class’s destructor is called, and the body of the destructor function is executed.

  2. Destructors for nonstatic member objects are called in the reverse order in which they appear in the class declaration. The optional member initialization list used in construction of these members does not affect the order of construction or destruction. (For more information about initializing members, see Initializing Bases and Members.)

  3. Destructors for nonvirtual base classes are called in the reverse order of declaration.

  4. Destructors for virtual base classes are called in the reverse order of declaration.


Destructors for Nonvirtual Base Classes

The destructors for nonvirtual base classes are called in the reverse order in which the base class names are declared. Consider the following class declaration:

class MultInherit : public Base1, public Base2
...

In the preceding example, the destructor for Base2 is called before the destructor for Base1.


Destructors for Virtual Base Classes

Destructors for virtual base classes are called in the reverse order of their appearance in a directed acyclic graph (depth-first, left-to-right, postorder traversal). Figure 11.1 depicts an inheritance graph.

Figure 11.1 Inheritance Graph Showing Virtual Base Classes

The following lists the class heads for the classes shown in Figure 11.1.

class A
class B
class C : virtual public A, virtual public B
class D : virtual public A, virtual public B
class E : public C, public D, virtual public B

To determine the order of destruction of the virtual base classes of an object of type E, the compiler builds a list by applying the following algorithm:

  1. Traverse the graph left, starting at the deepest point in the graph (in this case, E).

  2. Perform leftward traversals until all nodes have been visited. Note the name of the current node.

  3. Revisit the previous node (down and to the right) to find out whether the node being remembered is a virtual base class.

  4. If the remembered node is a virtual base class, scan the list to see whether it has already been entered. If it is not a virtual base class, ignore it.

  5. If the remembered node is not yet in the list, add it to the bottom of the list.

  6. Traverse the graph up and along the next path to the right.

  7. Go to step 2.

  8. When the last upward path is exhausted, note the name of the current node.

  9. Go to step 3.

  10. Continue this process until the bottom node is again the current node.

Therefore, for class E, the order of destruction is:

  1. The nonvirtual base class E.

  2. The nonvirtual base class D.

  3. The nonvirtual base class C.

  4. The virtual base class B.

  5. The virtual base class A.

This process produces an ordered list of unique entries. No class name appears twice. Once the list is constructed, it is walked in reverse order, and the destructor for each of the classes in the list from the last to the first is called.

The order of construction or destruction is primarily important when constructors or destructors in one class rely on the other component being created first or persisting longer — for example, if the destructor for A (in the graph in Figure 11.1) relied on B still being present when its code executed, or vice versa.

Such interdependencies between classes in an inheritance graph are inherently dangerous because classes derived later can alter which is the leftmost path, thereby changing the order of construction and destruction.


Explicit Destructor Calls

Calling a destructor explicitly is seldom necessary. However, it can be useful to perform cleanup of objects placed at absolute addresses. These objects are commonly allocated using a user-defined new operator that takes a placement argument. The delete operator cannot deallocate this memory because it is not allocated from the free store (for more information, see The new and delete Operators). A call to the destructor, however, can perform appropriate cleanup. To explicitly call the destructor for an object, s, of class String, use one of the following statements:

s.String::~String();     // Nonvirtual call
ps->String::~String();   // Nonvirtual call

s.~String();       // Virtual call
ps->~String();     // Virtual call

The notation for explicit calls to destructors, shown in the preceding, can be used regardless of whether the type defines a destructor. This allows you to make such explicit calls without knowing if a destructor is defined for the type. An explicit call to a destructor where none is defined has no effect.


Temporary Objects

In some cases, it is necessary for the compiler to create temporary objects. These temporary objects can be created for the following reasons:

  • To initialize a const reference with an initializer of a type different from that of the underlying type of the reference being initialized.

  • To store the return value of a function that returns a user-defined type. These temporaries are created only if your program does not copy the return value to an object. For example:
    UDT Func1();    //  Declare a function that returns a user-defined
                //   type.

...

Func1();        //  Call Func1, but discard return value.
                //  A temporary object is created to store the return
                //   value.

    Because the return value is not copied to another object, a temporary object is created. A more common case where temporaries are created is during the evaluation of an expression where overloaded operator functions must be called. These overloaded operator functions return a user-defined type that often is not copied to another object.

    Consider the expression ComplexResult = Complex1 + Complex2 + Complex3. The expression Complex1 + Complex2 is evaluated, and the result is stored in a temporary object. Next, the expression temporary + Complex3 is evaluated, and the result is copied to ComplexResult (assuming the assignment operator is not overloaded).

  • To store the result of a cast to a user-defined type. When an object of a given type is explicitly converted to a user-defined type, that new object is constructed as a temporary object.

Temporary objects have a lifetime that is defined by their point of creation and the point at which they are destroyed. Any expression that creates more than one temporary object eventually destroys them in the reverse order in which they were created. The points at which destruction occurs are shown in Table 11.3.

Table 11.3 Destruction Points for Temporary Objects

Reason Temporary Created | Destruction Point
Result of expression evaluation | All temporaries created as a result of expression evaluation are destroyed at the end of the expression statement (that is, at the semicolon), or at the end of the controlling expressions for for, if, while, do, and switch statements.
Result of expressions using the built-in (not overloaded) logical operators (|| and &&) | Immediately after the right operand. At this destruction point, all temporary objects created by evaluation of the right operand are destroyed.
Initializing const references | If an initializer is not an l-value of the same type as the reference being initialized, a temporary of the underlying object type is created and initialized with the initialization expression. This temporary object is destroyed immediately after the reference object to which it is bound is destroyed.


Conversions

Objects of a given class type can be converted to objects of another type. This is done by constructing an object of the target class type from the source class type and copying the result to the target object. This process is called conversion by constructor. Objects can also be converted by user-supplied conversion functions.

When standard conversions (described in Chapter 3, Standard Conversions) cannot completely convert from a given type to a class type, the compiler can select user-defined conversions to help complete the job. In addition to explicit type conversions, conversions take place when:

  • An initializer expression is not the same type as the object being initialized.

  • The type of argument used in a function call does not match the type of argument specified in the function declaration.

  • The type of the object being returned from a function does not match the return type specified in the function declaration.

  • Two expression operands must be of the same type.

  • An expression controlling an iteration or selection statement requires a different type from the one supplied.

A user-defined conversion is applied only if it is unambiguous; otherwise, an error message is generated. Ambiguity is checked at the point of usage. Hence, if the features that cause ambiguity are not used, a class can be designated with potential ambiguities and not generate any errors. Although there are many situations in which ambiguities arise, these are two leading causes of ambiguities:

  • A class type is derived using multiple inheritance, and it is unclear from which base class to select the conversion (see Ambiguity in Chapter 9).

  • An explicit type-conversion operator and a constructor for the same conversion exist (see Conversion Functions).

Both conversion by constructor and conversion by conversion functions obey access control rules, as described in Chapter 10, Member-Access Control. Access control is tested only after the conversion is found to be unambiguous.


Conversion Constructors

A constructor that can be called with a single argument is used for conversions from the type of the argument to the class type. Such a constructor is called a conversion constructor. Consider the following example:

class Point
{
public:
    Point();
    Point( int );
    ...
};

Sometimes a conversion is required but no conversion constructor exists in the class. These conversions cannot be performed by constructors. The compiler does not look for intermediate types through which to perform the conversion. For example, suppose a conversion exists from type Point to type Rect and a conversion exists from type int to type Point. The compiler does not supply a conversion from type int to type Rect by constructing an intermediate object of type Point.


Conversions and Constants

Although constants for built-in types such as int, long, and double can appear in expressions, no constants of class types are allowed (this is partly because classes usually describe an object complicated enough to make notation inconvenient). However, if conversion constructors from built-in types are supplied, constants of these built-in types can be used in expressions, and the conversions cause correct behavior. For example, a Money class can have conversions from types long and double:

class Money
{
public:
    Money( long );
    Money( double );
   ...
    Money operator+( const Money& );  // Overloaded addition operator.
};

Therefore, expressions such as the following can specify constant values:

Money AccountBalance = 37.89;
Money NewBalance = AccountBalance + 14L;

The second example involves the use of an overloaded addition operator, which is covered in the next chapter. Both examples cause the compiler to convert the constants to type Money before using them in the expressions.


Drawbacks of Conversion Constructors

Because the compiler can select a conversion constructor implicitly, you relinquish control over what functions are called when. If it is essential to retain full control, do not declare any constructors that take a single argument; instead, define “helper” functions to perform conversions, as in the following example:

#include <stdio.h>
#include <stdlib.h>

// Declare Money class.
class Money
{
public:
    Money();
// Define conversion functions that can only be called explicitly.
    static Money Convert( char * ch ) { return Money( ch ); }
    static Money Convert( double d )    { return Money( d ); };
    void  Print() { printf( "\n%f", _amount ); }
private:
    Money( char *ch ) { _amount = atof( ch ); }
    Money( double d ) { _amount = d; }
    double _amount;
};

void main()
{
    // Perform a conversion from type char * to type Money.
    Money Acct = Money::Convert( "57.29" );
    Acct.Print();
    // Perform a conversion from type double to type Money.
    Acct = Money::Convert( 33.29 );
    Acct.Print();
}

In the preceding code, the conversion constructors are private and cannot be used in type conversions. However, they can be invoked explicitly by calling the Convert functions. Because the Convert functions are static, they are accessible without referencing a particular object.


Conversion Functions

In conversion by constructors, described in the previous section, objects of one type can be implicitly converted to a particular class type. This section describes a means by which you can provide explicit conversions from a given class type to another type. Conversion from a class type is often accomplished using conversion functions. Conversion functions use the following syntax:

Syntax

conversion-function-name :

operator conversion-type-name ()

conversion-type-name :

type-specifier-list ptr-operatoropt

The following example specifies a conversion function that converts type Money to type double:

class Money
{
public:
    Money();
    operator double() { return _amount; }
private:
    double _amount;
};

Given the preceding class declaration, the following code can be written:

Money Account;
...
double CashOnHand = Account;

The initialization of CashOnHand with Account causes a conversion from type Account to type double.

Conversion functions are often called “cast operators” because they (along with constructors) are the functions called when a cast is used. The following example uses a cast, or explicit conversion, to print the current value of an object of type Money:

cout << (double)Account << endl;

Conversion functions are inherited in derived classes. Conversion operators hide only base-class conversion operators that convert to exactly the same type. Therefore, a user-defined operator int function does not hide a user-defined operator short function in a base class.

Only one user-defined conversion function is applied when performing implicit conversions. If there is no explicitly defined conversion function, the compiler does not look for intermediate types into which an object can be converted.

If a conversion is required that causes an ambiguity, an error is generated. Ambiguities arise when more than one user-defined conversion is available or when a user-defined conversion and a built-in conversion exist.

The following example illustrates a class declaration with a potential ambiguity:

#include <string.h>

class String
{
public:
    // Define constructor that converts from type char *.
    String( char *s ) { strcpy( _text, s ); }
    // Define conversion to type char *.
    operator char *() { return _text; }
    int operator==( const String &s )
    { return !strcmp( _text, s._text ); }
private:
    char _text[80];
};

int main()
{
    String s( "abcd" );
    char  *ch = "efgh";

    // Cause the compiler to select a conversion.
    return s == ch;
}

In the expression s == ch, the compiler has two choices and no way of determining which is correct. It can convert ch to an object of type String using the constructor and then perform the comparison using the user-defined operator==. Or it can convert s to a pointer of type char * using the conversion function and then perform a comparison of the pointers.

Because neither choice is “more correct” than the other, the compiler cannot determine the meaning of the comparison expression, and it generates an error.


Rules for Declaring Conversion Functions

The following four rules are used when declaring conversion functions (see Conversion Functions for syntax):

  • Classes, enumerations, and typedef names cannot be declared in the type-specifier-list. Therefore, the following code generates an error:
    operator struct String{ char string_storage; }();

    Instead, declare the String structure prior to the conversion function.

  • Conversion functions take no arguments. Specifying arguments generates an error.

  • Conversion functions have the return type specified by the conversion-type-name; specifying any return type for a conversion function generates an error.

  • Conversion functions can be declared as virtual.


The new and delete Operators

C++ supports dynamic allocation and deallocation of objects using the new and delete operators. These operators allocate memory for objects from a pool called the “free store.” The new operator calls the special function operator new, and the delete operator calls the special function operator delete.


The operator new Function

When a statement such as the following is encountered in a program, it translates into a call to the function operator new:

char *pch = new char[BUFFER_SIZE];

If the request is for zero bytes of storage, operator new returns a pointer to a distinct object (that is, repeated calls to operator new return different pointers). If there is insufficient memory for the allocation request, by default operator new returns NULL. You can change this default behavior by writing a custom exception-handling routine and calling the _set_new_handler run-time library function with your function name as its argument. For more details on the recovery scheme, see the following section, Handling Insufficient Memory Conditions.

The two scopes for operator new functions are described in Table 11.4.

Table 11.4 Scope for operator new Functions

Operator | Scope
::operator new | Global
class-name::operator new | Class

The first argument to operator new must be of type size_t (a type defined in STDDEF.H), and the return type is always void *.

The global operator new function is called when the new operator is used to allocate objects of built-in types, objects of class type that do not contain user-defined operator new functions, and arrays of any type. When the new operator is used to allocate objects of a class type where an operator new is defined, that class’s operator new is called.

An operator new function defined for a class is a static member function (which cannot, therefore, be virtual) that hides the global operator new function for objects of that class type. Consider the case where new is used to allocate and set memory to a given value:

#include <malloc.h>
#include <memory.h>

class Blanks
{
public:
    Blanks(){}
    void *operator new( size_t stAllocateBlock, char chInit );
};
void *Blanks::operator new( size_t stAllocateBlock, char chInit )
{
    void *pvTemp = malloc( stAllocateBlock );
    if( pvTemp != 0 )
        memset( pvTemp, chInit, stAllocateBlock );
    return pvTemp;
}

For discrete objects of type Blanks, the global operator new function is hidden. Therefore, the following code allocates an object of type Blanks and initializes it to 0xa5:

int main()
{
    Blanks *a5 = new( 0xa5 ) Blanks;

    return a5 != 0;
}

The argument supplied in parentheses to new is passed to Blanks::operator new as the chInit argument. However, the global operator new function is hidden, causing code such as the following to generate an error:

Blanks *SomeBlanks = new Blanks;

For previous versions of the compiler, nonclass types and all arrays (regardless of whether they were of class type) allocated using the new operator always used the global operator new function.

Beginning with Visual C++ 5.0, the compiler supports member array new and delete operators in a class declaration. For example:

class X {
public:
   void*   operator new[] (size_t);
   void      operator delete[] (void*);
};

void f() {
   X *pX = new X[5];
   delete [] pX;
}


Handling Insufficient Memory Conditions

Testing for failed memory allocation can be done with code such as the following:

int *pi = new int[BIG_NUMBER];

if( pi == 0 )
{
    cerr << "Insufficient memory" << endl;
    return -1;
}

There is an other ways to handle failed memory allocation requests: write a custom recovery routine to handle such a failure, then register your function by calling the _set_new_handler run-time function. This method is described in the following section.


Using _set_new_handler

In some circumstances, corrective action can be taken during memory allocation and the request can be fulfilled. To gain control when the global operator new function fails, use the _set_new_handler function (defined in NEW.H) as follows:

#include <stdio.h>
#include <new.h>

// Define a function to be called if new fails to allocate memory.
int MyNewHandler( size_t size )
{
    clog << "Allocation failed. Coalescing heap." << endl;

    // Call a fictitious function to recover some heap space.
    return CoalesceHeap();
}

void main()
{
    // Set the failure handler for new to be MyNewHandler.
    _set_new_handler( MyNewHandler );

    int *pi = new int[BIG_NUMBER];
}

In the preceding example, the first statement in main sets the new handler to MyNewHandler. The second statement tries to allocate a large block of memory using the new operator. When the allocation fails, control is transferred to MyNewHandler. The argument passed to MyNewHandler is the number of bytes requested. The value returned from MyNewHandler is a flag indicating whether allocation should be retried: a nonzero value indicates that allocation should be retried, and a zero value indicates that allocation has failed.

MyNewHandler prints a warning message and takes corrective action. If MyNewHandler returns a nonzero value, the new operator retries the allocation. When MyNewHandler returns a 0 the new operator stops trying and returns a zero value to the program.

The _set_new_handler function returns the address of the previous new handler. Therefore, if a new handler needs to be installed for a short time, the previous new handler can be reinstalled using code such as the following:

#include <new.h>

...

_PNH old_handler = _set_new_handler( MyNewHandler );

// Code that requires MyNewHandler.
...

// Reinstall previous new handler.
_set_new_handler( old_handler );

A call to _set_new_handler with an argument of 0 causes the new handler to be removed. There is no default new handler.

The new handler you specify can have any name, but it must be a function returning type int (nonzero indicates the new handler succeeded, and zero indicates that it failed).

If a user-defined operator new is provided, the new handler functions are not automatically called on failure.

The prototype for _set_new_handler and the type _PNH is defined in NEW.H:

_PNH _set_new_handler( _PNH );

The type _PNH is a pointer to a function that returns type int and takes a single argument of type size_t.


The operator delete Function

Memory that is dynamically allocated using the new operator can be freed using the delete operator. The delete operator calls the operator delete function, which frees memory back to the available pool. Using the delete operator also causes the class destructor (if there is one) to be called.

There are global and class-scoped operator delete functions. Only one operator delete function can be defined for a given class; if defined, it hides the global operator delete function. The global operator delete function is always called for arrays of any type.

The global operator delete function, if declared, takes a single argument of type void *, which contains a pointer to the object to deallocate. The return type is void (operator delete cannot return a value). Two forms exist for class-member operator delete functions:

void operator delete( void * );
void operator delete( void *, size_t );

Only one of the preceding two variants can be present for a given class. The first form works as described for global operator delete. The second form takes two arguments, the first of which is a pointer to the memory block to deallocate and the second of which is the number of bytes to deallocate. The second form is particularly useful when an operator delete function from a base class is used to delete an object of a derived class.

The operator delete function is static; therefore, it cannot be virtual. The operator delete function obeys access control, as described in Chapter 10, Member-Access Control.

The following example shows user-defined operator new and operator delete functions designed to log allocations and deallocations of memory:

#include <iostream.h>
#include <stdlib.h>

int fLogMemory = 0;       // Perform logging (0=no; nonzero=yes)?
int cBlocksAllocated = 0;  // Count of blocks allocated.
// User-defined operator new.
void *operator new( size_t stAllocateBlock )
{
    static fInOpNew = 0;    // Guard flag.

    if( fLogMemory && !fInOpNew )
    {
        fInOpNew = 1;
        clog << "Memory block "   << ++cBlocksAllocated
             << " allocated for " << stAllocateBlock
             << " bytes\n";
        fInOpNew = 0;
    }

    return malloc( stAllocateBlock );
}
// User-defined operator delete.
void operator delete( void *pvMem )
{
    static fInOpDelete = 0;    // Guard flag.
    if( fLogMemory && !fInOpDelete )
    {
        fInOpDelete = 1;
        clog << "Memory block " << --cBlocksAllocated
             << " deallocated\n";
        fInOpDelete = 0;
    }

    free( pvMem );
}

int main( int argc, char *argv[] )
{
    fLogMemory = 1;  // Turn logging on.
    if( argc > 1 )
    for( int i = 0; i < atoi( argv[1] ); ++i )
    {
        char *pMem = new char[10];
        delete[] pMem;
    }

    return cBlocksAllocated;
}

The preceding code can be used to detect “memory leakage” — that is, memory that is allocated on the free store but never freed. To perform this detection, the global new and delete operators are redefined to count allocation and deallocation of memory.

Beginning with Visual C++ 5.0, the compiler supports member array new and delete operators in a class declaration. For example:

class X {
public:
   void*   operator new[] (size_t);
   void      operator delete[] (void*);
};

void f() {
   X *pX = new X[5];
   delete [] pX;
}


Initialization Using Special Member Functions

This section describes initialization using special member functions. It expands on the following discussions of initialization:

  • Initializing Aggregates in Chapter 7, which describes how to initialize arrays of nonclass types and objects of simple class types. These simple class types cannot have private or protected members, and they cannot have base classes.

  • Constructors, which explains how to initialize class-type objects using special constructor functions.

The default method of initialization is to perform a bit-for-bit copy from the initializer into the object to be initialized. This technique is applicable only to:

  • Objects of built-in types. For example:
    int i = 100;
  • Pointers. For example:
    int i;
int *pi = &i;
  • References. For example:
    String sFileName( "FILE.DAT" );
String &rs = sFileName;
  • Objects of class type, where the class has no private or protected members, no virtual functions, and no base classes. For example:
    struct Point
{
    int x, y;
};

Point pt = { 10, 20 };   // Static storage class only

Classes can specify more refined initialization by defining constructor functions. (For more information about declaring such functions, see Constructors.) If an object is of a class type that has a constructor, the object must be initialized, or there must be a default constructor. Objects that are not specifically initialized invoke the class’s default constructor.


Explicit Initialization

C++ supports two forms of explicit initialization.

  • Supplying an initializer list in parentheses:
    String sFileName( "FILE.DAT" );

    The items in the parenthesized list are considered arguments to the class constructor. This form of initialization enables initialization of an object with more than one value and can also be used in conjunction with the new operator. For example:

    Rect *pRect = new Rect( 10, 15, 24, 97 );
  • Supplying a single initializer using the equal-sign initialization syntax. For example:
    String sFileName = "FILE.DAT";

    Although the preceding example works the same way as the example shown for String in the first list item, the syntax is not adaptable to use with objects allocated on the free store.

    The single expression on the right of the equal sign is taken as the argument to the class’s copy constructor; therefore, it must be a type that can be converted to the class type.

    Note that because the equal sign (=) in the context of initialization is different from an assignment operator, overloading operator= has no effect on initialization.

The equal-sign initialization syntax is different from the function-style syntax, even though the generated code is identical in most cases. The difference is that when the equal-sign syntax is used, the compiler has to behave as if the following sequence of events were taking place:

  • Creating a temporary object of the same type as the object being initialized.

  • Copying the temporary object to the object.

The constructor must be accessible before the compiler can perform these steps. Even though the compiler can eliminate the temporary creation and copy steps in most cases, an inaccessible copy constructor causes equal-sign initialization to fail. Consider the following example:

class anInt
{
    anInt( const anInt& );    //  Private copy constructor.
public:
    anInt( int );             //  Public int constructor.
};
...
anInt myInt = 7;              //  Access-control violation. Attempt to
                              //   reference private copy constructor.
anInt myInt( 7 );             //  Correct; no copy constructor called.

When a function is called, class-type arguments passed by value and objects returned by value are conceptually initialized using the form:

type-name name = value

For example:

String s = "C++";

Therefore, it follows that the argument type must be a type that can be converted to the class type being passed as an argument. The class’s copy constructor, as well as user-defined conversion operators or constructors that accept the type of the actual argument, must be public.

In expressions that use the new operator, the objects allocated on the free store are conceptually initialized using the form:

type-name name( initializer1, initializer2, ... initializern )

For example:

String *ps = new String( "C++" );

Initializers for base-class components and member objects of a class are also conceptually initialized this way. (For more information, see Initializing Bases and Members.)


Initializing Arrays

If a class has a constructor, arrays of that class are initialized by a constructor. If there are fewer items in the initializer list than elements in the array, the default constructor is used for the remaining elements. If no default constructor is defined for the class, the initializer list must be complete — that is, there must be one initializer for each element in the array.

Consider the Point class that defines two constructors:

class Point
{
public:
    Point();           // Default constructor.
    Point( int, int ); // Construct from two ints.
    ...
};

An array of Point objects can be declared as follows:

Point aPoint[3] = {
    Point( 3, 3 )     // Use int, int constructor.
};

The first element of aPoint is constructed using the constructor Point( int, int ); the remaining two elements are constructed using the default constructor.

Static member arrays (whether const or not) can be initialized in their definitions (outside the class declaration). For example:

class WindowColors
{
public:
    static const char *rgszWindowPartList[7];
    ...
};
const char *WindowColors::rgszWindowPartList[7] = {
    "Active Title Bar", "Inactive Title Bar", "Title Bar Text",
    "Menu Bar", "Menu Bar Text", "Window Background", "Frame"   };


Initializing Static Objects

Global static objects are initialized in the order they occur in the source. They are destroyed in the reverse order. Across translation units, however, the order of initialization is dependent on how the object files are arranged by the linker; the order of destruction still takes place in the reverse of that in which objects were constructed.

Local static objects are initialized when they are first encountered in the program flow, and they are destroyed in the reverse order at program termination. Destruction of local static objects occurs only if the object was encountered and initialized in the program flow.


Initializing Bases and Members

An object of a derived class is made up of a component that represents each base class and a component that is unique to the particular class. Objects of classes that have member objects may also contain instances of other classes. This section describes how these component objects are initialized when an object of the class type is created.

To perform the initialization, the constructor-initializer, or ctor-initializer, syntax is used.

Syntax

ctor-initializer :

mem-initializer-list

mem-initializer-list :

mem-initializer
mem-initializer , mem-initializer-list

mem-initializer :

complete-class-name ( expression-listopt )
identifier ( expression-listopt )

This syntax, used in constructors, is described more fully in the next section, Initializing Member Objects, and in Initializing Base Classes.


Initializing Member Objects

Classes can contain member objects of class type, but to ensure that initialization requirements for the member objects are met, one of the following conditions must be met:

  • The contained object’s class requires no constructor.

  • The contained object’s class has an accessible default constructor.

  • The containing class’s constructors all explicitly initialize the contained object.

The following example shows how to perform such an initialization:

// Declare a class Point.
class Point
{
public:
    Point( int x, int y ) { _x = x; _y = y; }
private:
    int _x, _y;
};

// Declare a rectangle class that contains objects of type Point.
class Rect
{
public:
    Rect( int x1, int y1, int x2, int y2 );
private:
    Point _topleft, _bottomright;
};

//  Define the constructor for class Rect. This constructor
//   explicitly initializes the objects of type Point.
Rect::Rect( int x1, int y1, int x2, int y2 ) :
_topleft( x1, y1 ), _bottomright( x2, y2 )
{
}

The Rect class, shown in the preceding example, contains two member objects of class Point. Its constructor explicitly initializes the objects _topleft and _bottomright. Note that a colon follows the closing parenthesis of the constructor (in the definition). The colon is followed by the member names and arguments with which to initialize the objects of type Point.

Warning The order in which the member initializers are specified in the constructor does not affect the order in which the members are constructed; the members are constructed in the order in which they are declared in the class.

Reference and const member objects must be initialized using the member initialization syntax shown in Syntax in Initializing Bases and Members. There is no other way to initialize these objects.


Initializing Base Classes

Direct base classes are initialized in much the same way as member objects. Consider the following example:

//  Declare class Window.
class Window
{
public:
    Window( Rect rSize );
    ...
};

//  Declare class DialogBox, derived from class Window.
class DialogBox : public Window
{
public:
    DialogBox( Rect rSize );
    ...
};

//  Define the constructor for DialogBox. This constructor
//   explicitly initializes the Window subobject.
DialogBox::DialogBox( Rect rSize ) : Window( rSize )
{
}

Note that in the constructor for DialogBox, the Window base class is initialized using the argument rSize. This initialization consists of the name of the base class to initialize, followed by a parenthesized list of arguments to the class’s constructor.

In initialization of base classes, the object that is not the subobject representing a base class’s component is considered a “complete object.” The complete object’s class is considered the “most derived” class for the object.

The subobjects representing virtual base classes are initialized by the constructor for the most derived class. That means that where virtual derivation is specified, the most derived class must explicitly initialize the virtual base class, or the virtual base class must have a default constructor. Initializations for virtual base classes that appear in constructors for classes other than the most derived class are ignored.

Although initialization of base classes is usually restricted to direct base classes, a class constructor can initialize an indirect virtual base class.


Initialization Order of Bases and Members

Base classes and member objects are initialized in the following order:

  1. Virtual base classes are initialized in the order in which they appear in the directed acyclic graph. For information about using the directed acyclic graph to construct a list of unique subobjects, see Virtual Base Classes in Chapter 9. (Note that these subobjects are destroyed by walking the same list in reverse.) For more information about how the directed acyclic graph is traversed, see Order of Destruction.

  2. Nonvirtual base classes are initialized in the order in which they are declared in the class declaration.

  3. Member objects are initialized in the order in which the objects are declared in the class.

The order in which base classes and member objects are initialized is not affected by the order in which the member initializers or base-class initializers appear in the member-initializer-list of the constructor.


Scope of Initializers

Initializers for base classes and member objects are evaluated in the scope of the constructor with which they are declared. Therefore, they can refer implicitly to class-member data.


Copying Class Objects

Two operations cause objects to be copied:

  • Assignment. When one object’s value is assigned to another object, the first object is copied to the second object. Therefore:
    Point a, b;
...
a = b;

    causes the value of b to be copied to a.

  • Initialization. Initialization occurs at the point of declaration of a new object, when arguments are passed to functions by value, and when values are returned from functions by value.

The programmer can define the semantics of “copy” for objects of class type. For example, consider the following code:

TextFile a, b;
a.Open( "FILE1.DAT" );
b.Open( "FILE2.DAT" );
b = a;

The preceding code could mean “copy the contents of FILE1.DAT to FILE2.DAT,” or it could mean “ignore FILE2.DAT and make b a second handle to FILE1.DAT.” The programmer is responsible for attaching appropriate copying semantics to each class.

Copying is done in one of two ways:

  • Assignment (using the assignment operator, operator=).

  • Initialization (using the copy constructor). (For more information about the copy constructor, see Rules for Declaring Constructors.)

Any given class can implement one or both copy methods. If neither method is implemented, assignment is handled as a member-by-member (“memberwise”) assignment, and initialization is handled as a member-by-member initialization. Memberwise assignment is covered in more detail in Memberwise Assignment and Initialization.

The copy constructor takes a single argument of type class-name&, where class-name is the name of the class for which the constructor is defined. For example:

class Window
{
public:
    Window( const Window& ); // Declare copy constructor.
    ...
};

Note The type of the copy constructor’s argument should be const class-name& whenever possible. This prevents the copy constructor from accidentally changing the object from which it is copying. It also allows copying from const objects.


Compiler-Generated Copying

Compiler-generated copy constructors, like user-defined copy constructors, have a single argument of type “reference to class-name.” An exception is when all base classes and member classes have copy constructors declared as taking a single argument of type const class-name&. In such a case, the compiler-generated copy constructor’s argument is also const.

When the argument type to the copy constructor is not const, initialization by copying a const object generates an error. The reverse is not true: If the argument is const, initialization by copying an object that is not const.

Compiler-generated assignment operators follow the same pattern with regard to const. They take a single argument of type class-name& unless the assignment operators in all base and member classes take arguments of type const class-name&. In this case, the class’s generated assignment operator takes a const argument.

Note When virtual base classes are initialized by copy constructors, compiler-generated or user-defined, they are initialized only once: at the point when they are constructed.

The implications are similar to those of the copy constructor. When the argument type is not const, assignment from a const object generates an error. The reverse is not true: If a const value is assigned to a value that is not const, the assignment succeeds.

For more information about overloaded assignment operators, see Assignment in Chapter 12.


Memberwise Assignment and Initialization

The methods for default assignment and initialization are “memberwise assignment” and “memberwise initialization,” respectively. Memberwise assignment consists of copying one object to the other, a member at a time, as if assigning each member individually. Memberwise initialization consists of copying one object to the other, a member at a time, as if initializing each member individually. The primary difference between the two is that memberwise assignment invokes each member’s assignment operator (operator=), whereas memberwise initialization invokes each member’s copy constructor.

Memberwise assignment is performed only by the assignment operator declared in the form:

type& type :: operator=( [const | volatile] type& )

Default assignment operators for memberwise assignment cannot be generated if any of the following conditions exist:

  • A member class has const members.

  • A member class has reference members.

  • A member class or its base class has a private assignment operator (operator=).

  • A base class or member class has no assignment operator (operator=).

Default copy constructors for memberwise initialization cannot be generated if the class or one of its base classes has a private copy constructor or if any of the following conditions exist:

  • A member class has const members.

  • A member class has reference members.

  • A member class or its base class has a private copy constructor.

  • A base class or member class has no copy constructor.

The default assignment operators and copy constructors for a given class are always declared, but they are not defined unless both of the following conditions are met:

  • The class does not provide a user-defined function for this copy.

  • The program requires that the function be present. This requirement exists if an assignment or initialization is encountered that requires memberwise copying or if the address of the class’s operator= function is taken.

If both of these conditions are not met, the compiler is not required to generate code for the default assignment operator and copy constructor functions (elimination of such code is an optimization performed by the Microsoft C++ compiler). Specifically, if the class declares a user-defined operator= that takes an argument of type “reference to class-name,” no default assignment operator is generated. If the class declares a copy constructor, no default copy constructor is generated.

Therefore, for a given class A, the following declarations are always present:

//  Implicit declarations of copy constructor
//   and assignment operator.
A::A( const A& );
A& A::operator=( const A& );

The definitions are supplied only if required (according to the preceding criteria). The copy constructor functions shown in the preceding example are considered public member functions of the class.

Default assignment operators allow objects of a given class to be assigned to objects of a public base-class type. Consider the following code:

class Account
{
public:
    // Public member functions
    ...
private:
    double _balance;
};

class Checking : public Account
{
private:
    int _fOverdraftProtect;
};

...

Account account;
Checking checking;

account = checking;

In the preceding example, the assignment operator chosen is Account::operator=. Because the default operator= function takes an argument of type Account& (reference to Account), the Account subobject of checking is copied to account; fOverdraftProtect is not copied.


Overloading

This chapter explains how to use C++ overloaded functions and overloaded operators. The following topics are included:

  • Overview

  • Declaration matching

  • Argument matching

  • Address of overloaded functions

  • Overloaded operators


Overview of Overloading

With the C++ language, you can overload functions and operators. Overloading is the practice of supplying more than one definition for a given function name in the same scope. The compiler is left to pick the appropriate version of the function or operator based on the arguments with which it is called. For example:

double max( double d1, double d2 )
{
    return ( d1 > d2 ) ? d1 : d2;
}

int max( int i1, int i2 )
{
    return ( i1 > i2 ) ? i1 : i2;
}

The function max is considered an overloaded function. It can be used in code such as the following:

main()
{
    int    i = max( 12, 8 );
    double d = max( 32.9, 17.4 );

    return i + (int)d;
}

In the first case, where the maximum value of two variables of type int is being requested, the function max( int, int ) is called. However, in the second case, the arguments are of type double, so the function max( double, double ) is called.


Argument Type Differences

Overloaded functions differentiate between argument types that take different initializers. Therefore, an argument of a given type and a reference to that type are considered the same for the purposes of overloading. They are considered the same because they take the same initializers. For example, max( double, double ) is considered the same as max( double &, double & ). Declaring two such functions causes an error.

For the same reason, function arguments of a type modified by const or volatile are not treated differently than the base type for the purposes of overloading.

However, the function overloading mechanism can distinguish between references that are qualified by const and volatile and references to the base type. This makes code such as the following possible:

#include <iostream.h>

class Over
{
public:
    Over() { cout << "Over default constructor\n"; }
    Over( Over &o ) { cout << "Over&\n"; }
    Over( const Over &co ) { cout << "const Over&\n"; }
    Over( volatile Over &vo ) { cout << "volatile Over&\n"; }
};

void main()
{
    Over o1;            // Calls default constructor.
    Over o2( o1 );      // Calls Over( Over& ).
    const Over o3;      // Calls default constructor.
    Over o4( o3 );      // Calls Over( const Over& ).
    volatile Over o5;   // Calls default constructor.
    Over o6( o5 );      // Calls Over( volatile Over& ).
}

Pointers to const and volatile objects are also considered different from pointers to the base type for the purposes of overloading.


Restrictions on Overloaded Functions

Several restrictions govern an acceptable set of overloaded functions:

  • Any two functions in a set of overloaded functions must have different argument lists.

  • Overloading functions with argument lists of the same types, based on return type alone, is an error.

Microsoft Specific

You can overload operator new solely on the basis of return type — specifically, on the basis of the memory-model modifier specified.

END Microsoft Specific

  • Member functions cannot be overloaded solely on the basis of one being static and the other nonstatic.

  • typedef declarations do not define new types; they introduce synonyms for existing types. They do not affect the overloading mechanism. Consider the following code:
    typedef char * PSTR;

void Print( char *szToPrint );
void Print( PSTR szToPrint );

    The preceding two functions have identical argument lists. PSTR is a synonym for type char *. In member scope, this code generates an error.

  • Enumerated types are distinct types and can be used to distinguish between overloaded functions.

  • The types “array of ” and “pointer to” are considered identical for the purposes of distinguishing between overloaded functions. This is true only for singly dimensioned arrays. Therefore, the following overloaded functions conflict and generate an error message:
    void Print( char *szToPrint );
void Print( char szToPrint[] );

    For multiply dimensioned arrays, the second and all succeeding dimensions are considered part of the type. Therefore, they are used in distinguishing between overloaded functions:

    void Print( char szToPrint[] );
void Print( char szToPrint[][7] );
void Print( char szToPrint[][9][42] );


Declaration Matching

Any two function declarations of the same name in the same scope can refer to the same function, or to two discrete functions that are overloaded. If the argument lists of the declarations contain arguments of equivalent types (as described in the previous section), the function declarations refer to the same function. Otherwise, they refer to two different functions that are selected using overloading.

Class scope is strictly observed; therefore, a function declared in a base class is not in the same scope as a function declared in a derived class. If a function in a derived class is declared with the same name as a function in the base class, the derived-class function hides the base-class function instead of causing overloading.

Block scope is strictly observed; therefore, a function declared in file scope is not in the same scope as a function declared locally. If a locally declared function has the same name as a function declared in file scope, the locally declared function hides the file-scoped function instead of causing overloading. For example:

#include <iostream.h>

void func( int i )
{
    cout << "Called file-scoped func : " << i << endl;
}

void func( char *sz )
{
    cout << "Called locally declared func : " << sz << endl;
}

void main()
{
    // Declare func local to main.
    extern void func( char *sz );

    func( 3 );    // Error. func( int ) is hidden.
    func( "s" );
}

The preceding code shows two definitions from the function func. The definition that takes an argument of type char * is local to main because of the extern statement. Therefore, the definition that takes an argument of type int is hidden, and the first call to func is in error.

For overloaded member functions, different versions of the function can be given different access privileges. They are still considered to be in the scope of the enclosing class and thus are overloaded functions. Consider the following code, in which the member function Deposit is overloaded; one version is public, the other, private:

class Account
{
public:
    Account();
    double Deposit( double dAmount, char *szPassword );
private:
    double Deposit( double dAmount );
    int    Validate( char *szPassword );
};

The intent of the preceding code is to provide an Account class in which a correct password is required to perform deposits. This is accomplished using overloading. The following code shows how this class can be used and also shows an erroneous call to the private member, Deposit:

void main()
{
    // Allocate a new object of type Account.
    Account *pAcct = new Account;

    // Deposit $57.22. Error: calls a private function.
    pAcct->Deposit( 57.22 );

    // Deposit $57.22 and supply a password. OK: calls a
    //  public function.
    pAcct->Deposit( 52.77, "pswd" );
}

double Account::Deposit( double dAmount, char *szPassword )
{
    if( Validate( szPassword ) )
        return Deposit( dAmount );
    else
        return 0.0;
}

Note that the call to Deposit in Account::Deposit calls the private member function. This call is correct because Account::Deposit is a member function and therefore has access to the private members of the class.


Argument Matching

Overloaded functions are selected for the best match of function declarations in the current scope to the arguments supplied in the function call. If a suitable function is found, that function is called. “Suitable” in this context means one of the following:

  • An exact match was found.

  • A trivial conversion was performed.

  • An integral promotion was performed.

  • A standard conversion to the desired argument type exists.

  • A user-defined conversion (either conversion operator or constructor) to the desired argument type exists.

  • Arguments represented by an ellipsis were found.

The compiler creates a set of candidate functions for each argument. Candidate functions are functions in which the actual argument in that position can be converted to the type of the formal argument.

A set of “best matching functions” is built for each argument, and the selected function is the intersection of all the sets. If the intersection contains more than one function, the overloading is ambiguous and generates an error. The function that is eventually selected is always a better match than every other function in the group for at least one argument. If this is not the case (if there is no clear winner), the function call generates an error.

Consider the following declarations (the functions are marked Variant 1, Variant 2, and Variant 3, for identification in the following discussion):

Fraction &Add( Fraction &f, long l );       // Variant 1
Fraction &Add( long l, Fraction &f );       // Variant 2
Fraction &Add( Fraction &f, Fraction &f );  // Variant 3

Fraction F1, F2;

Consider the following statement:

F1 = Add( F2, 23 );

The preceding statement builds two sets:

Set 1: Candidate Functions That Have First Argument of Type Fraction | Set 2: Candidate Functions Whose Second Argument Can Be Converted to Type int
Variant 1 | Variant 1 (int can be converted to long using a standard conversion)
Variant 3 |

Functions in Set 2 are functions for which there are implicit conversions from actual parameter type to formal parameter type, and among such functions there is a function for which the “cost” of converting the actual parameter type to its formal parameter type is the smallest.

The intersection of these two sets is Variant 1. An example of an ambiguous function call is:

F1 = Add( 3, 6 );

The preceding function call builds the following sets:

Set 1: Candidate Functions That Have First Argument of Type int | Set 2: Candidate Functions That Have Second Argument of Type int
Variant 2 (int can be converted to long using a standard conversion) | Variant 1 (int can be converted to long using a standard conversion)

Note that the intersection between these two sets is empty. Therefore, the compiler generates an error message.

For argument matching, a function with n default arguments is treated as n+1 separate functions, each with a different number of arguments.

The ellipsis (...) acts as a wildcard; it matches any actual argument. This can lead to many ambiguous sets, if you do not design your overloaded function sets with extreme care.

Note Ambiguity of overloaded functions cannot be determined until a function call is encountered. At that point, the sets are built for each argument in the function call, and you can determine whether an unambiguous overload exists. This means that ambiguities can remain in your code until they are evoked by a particular function call.


Argument Matching and the this Pointer

Class member functions are treated differently, depending on whether they are declared as static. Because nonstatic functions have an implicit argument that supplies the this pointer, nonstatic functions are considered to have one more argument than static functions; otherwise, they are declared identically.

These nonstatic member functions require that the implied this pointer match the object type through which the function is being called, or, for overloaded operators, they require that the first argument match the object on which the operator is being applied. (For more information about overloaded operators, see Overloaded Operators.)

Unlike other arguments in overloaded functions, no temporary objects are introduced and no conversions are attempted when trying to match the this pointer argument.

When the – > member-selection operator is used to access a member function, the this pointer argument has a type of class-name * const. If the members are declared as const or volatile, the types are const class-name * const and volatile class-name * const, respectively.

The . member-selection operator works exactly the same way, except that an implicit & (address-of) operator is prefixed to the object name. The following example shows how this works:

// Expression encountered in code
obj.name

// How the compiler treats it
(&obj)->name

The left operand of the –>* and .* (pointer to member) operators are treated the same way as the . and –> (member-selection) operators with respect to argument matching.


Argument Matching and Conversions

When the compiler tries to match actual arguments against the arguments in function declarations, it can supply standard or user-defined conversions to obtain the correct type if no exact match can be found. The application of conversions is subject to these rules:

  • Sequences of conversions that contain more than one user-defined conversion are not considered.

  • Sequences of conversions that can be shortened by removing intermediate conversions are not considered.

The resultant sequence of conversions, if any, is called the best matching sequence. There are several ways to convert an object of type int to type unsigned long using standard conversions (described in Chapter 3, Standard Conversions):

  • Convert from int to long and then from long to unsigned long.

  • Convert from int to unsigned long.

The first sequence, although it achieves the desired goal, is not the best matching sequence — a shorter sequence exists.

Table 12.1 shows a group of conversions, called trivial conversions, that have a limited effect on determining of which sequence is the best matching. The instances in which trivial conversions affect choice of sequence are discussed in the list following the table.

Table 12.1 Trivial Conversions

Convert from Type | Convert to Type
type-name | type-name&
type-name& | type-name
type-name[ ] | type-name*
type-name( argument-list ) | (*type-name) ( argument-list )
type-name | const type-name
type-name | volatile type-name
type-name* | const type-name*
type-name* | volatile type-name*

The sequence in which conversions are attempted is as follows:

  1. Exact match. An exact match between the types with which the function is called and the types declared in the function prototype is always the best match. Sequences of trivial conversions are classified as exact matches. However, sequences that do not make any of these conversions are considered better than sequences that convert:
    • From pointer, to pointer to const (type * to const type *).

    • From pointer, to pointer to volatile (type * to volatile type *).

    • From reference, to reference to const (type & to const type &).

    • From reference, to reference to volatile (type & to volatile type &).
  2. Match using promotions. Any sequence not classified as an exact match that contains only integral promotions, conversions from float to double, and trivial conversions is classified as a match using promotions. Although not as good a match as any exact match, a match using promotions is better than a match using standard conversions.

  3. Match using standard conversions. Any sequence not classified as an exact match or a match using promotions that contains only standard conversions and trivial conversions is classified as a match using standard conversions. Within this category, the following rules are applied:
    • Conversion from a pointer to a derived class, to a pointer to a direct or indirect base class is preferable to converting to void * or const void *.

    • Conversion from a pointer to a derived class, to a pointer to a base class produces a better match the closer the base class is to a direct base class. Suppose the class hierarchy is as shown in Figure 12.1.

Figure 12.1 Graph Illustrating Preferred Conversions

Conversion from type D* to type C* is preferable to conversion from type D* to type B*. Similarly, conversion from type D* to type B* is preferable to conversion from type D* to type A*.

This same rule applies to reference conversions. Conversion from type D& to type C& is preferable to conversion from type D& to type B&, and so on.

This same rule applies to pointer-to-member conversions. Conversion from type T D::* to type T C::* is preferable to conversion from type T D::* to type T B::*, and so on (where T is the type of the member).

The preceding rule applies only along a given path of derivation. Consider the graph shown in Figure 12.2.

Figure 12.2 Multiple-Inheritance Graph Illustrating Preferred Conversions

Conversion from type C* to type B* is preferable to conversion from type C* to type A*. The reason is that they are on the same path, and B* is closer. However, conversion from type C* to type D* is not preferable to conversion to type A*; there is no preference because the conversions follow different paths.

  4. Match with user-defined conversions. This sequence cannot be classified as an exact match, a match using promotions, or a match using standard conversions. The sequence must contain only user-defined conversions, standard conversions, or trivial conversions to be classified as a match with user-defined conversions. A match with user-defined conversions is considered a better match than a match with an ellipsis but not as good a match as a match with standard conversions.

  5. Match with an ellipsis. Any sequence that matches an ellipsis in the declaration is classified as a match with an ellipsis. This is considered the weakest match.

User-defined conversions are applied if no built-in promotion or conversion exists. These conversions are selected on the basis of the type of the argument being matched. Consider the following code:

class UDC
{
public:
    operator int();
    operator long();
};

void Print( int i );
...
UDC udc;
Print( udc );

The available user-defined conversions for class UDC are from type int and type long. Therefore, the compiler considers conversions for the type of the object being matched: UDC. A conversion to int exists, and it is selected.

During the process of matching arguments, standard conversions can be applied to both the argument and the result of a user-defined conversion. Therefore, the following code works:

void LogToFile( long l );
...
UDC udc;
LogToFile( udc );

In the preceding example, the user-defined conversion, operator long, is invoked to convert udc to type long. If no user-defined conversion to type long had been defined, the conversion would have proceeded as follows: Type UDC would have been converted to type int using the user-defined conversion. Then the standard conversion from type int to type long would have been applied to match the argument in the declaration.

If any user-defined conversions are required to match an argument, the standard conversions are not used when evaluating the best match. This is true even if more than one candidate function requires a user-defined conversion; in such a case, the functions are considered equal. For example:

class UDC1
{
public:
    UDC1( int );  // User-defined conversion from int.
};

class UDC2
{
public:
    UDC2( long ); // User-defined conversion from long.
};

...

void Func( UDC1 );
void Func( UDC2 );

...

Func( 1 );

Both versions of Func require a user-defined conversion to convert type int to the class type argument. The possible conversions are:

  • Convert from type int to type UDC1 (a user-defined conversion).

  • Convert from type int to type long; then convert to type UDC2 (a two-step conversion).

Even though the second of these requires a standard conversion, as well as the user-defined conversion, the two conversions are still considered equal.

Note User-defined conversions are considered conversion by construction or conversion by initialization (conversion function). Both methods are considered equal when considering the best match.


Address of Overloaded Functions

Use of a function name without arguments returns the address of that function. For example:

int Func( int i, int j );
int Func( long l );

...

int (*pFunc) ( int, int ) = Func;

In the preceding example, the first version of Func is selected, and its address is copied into pFunc.

The compiler determines which version of the function to select by finding a function with an argument list that exactly matches that of the target. The arguments in the overloaded function declarations are matched against one of the following:

  • An object being initialized (as shown in the preceding example)

  • The left side of an assignment statement

  • A formal argument to a function

  • A formal argument to a user-defined operator

  • A function return type

If no exact match is found, the expression that takes the address of the function is ambiguous and an error is generated.

Note that although a nonmember function, Func, was used in the preceding example, the same rules are applied when taking the address of overloaded member functions.


Overloaded Operators

With C++, you can redefine the function of most built-in operators. These operators can be redefined, or “overloaded,” globally or on a class-by-class basis. Overloaded operators are implemented as functions and can be class-member or global functions.

The name of an overloaded operator is operator x, where x is the operator as it appears in Table 12.2. For example, to overload the addition operator, you define a function called operator+. Similarly, to overload the addition/assignment operator, +=, define a function called operator+=.

Although these operators are usually called implicitly by the compiler when they are encountered in code, they can be invoked explicitly the same way as any member or nonmember function is called:

Point pt;

pt.operator+( 3 );  // Call addition operator to add 3 to pt.

Table 12.2 Redefinable Operators

Operator | Name | Type
, | Comma | Binary
! | Logical NOT | Unary
!= | Inequality | Binary
% | Modulus | Binary
%= | Modulus/assignment | Binary
& | Bitwise AND | Binary
& | Address-of | Unary
&& | Logical AND | Binary
&= | Bitwise AND/assignment | Binary
( ) | Function call | —
* | Multiplication | Binary
* | Pointer dereference | Unary
*= | Multiplication/assignment | Binary
+ | Addition | Binary
+ | Unary Plus | Unary
++ | Increment1 | Unary
+= | Addition/assignment | Binary
– | Subtraction | Binary
– | Unary negation | Unary
–– | Decrement1 | Unary
–= | Subtraction/assignment | Binary
–> | Member selection | Binary
–>* | Pointer-to-member selection | Binary
/ | Division | Binary
/= | Division/assignment | Binary
< | Less than | Binary
<< | Left shift | Binary
<<= | Left shift/assignment | Binary
<= | Less than or equal to | Binary
= | Assignment | Binary
== | Equality | Binary
> | Greater than | Binary
>= | Greater than or equal to | Binary
>> | Right shift | Binary
>>= | Right shift/assignment | Binary
[ ] | Array subscript | —
^ | Exclusive OR | Binary
^= | Exclusive OR/assignment | Binary
| | Bitwise inclusive OR | Binary
|= | Bitwise inclusive OR/assignment | Binary
|| | Logical OR | Binary
~ | One’s complement | Unary
delete | delete | —
new | new | —

1 Two versions of the unary increment and decrement operators exist: preincrement and postincrement.

The constraints on the various categories of overloaded operators are described in Unary Operators, Binary Operators, Assignment, Function Call, Subscripting, Class-Member Access, and Increment and Decrement.

The operators shown in Table 12.3 cannot be overloaded.

Table 12.3 Nonredefinable Operators

Operator | Name
. | Member selection
.* | Pointer-to-member selection
:: | Scope resolution
? : | Conditional
# | Preprocessor symbol
## | Preprocessor symbol


General Rules for Operator Overloading

The following rules constrain how overloaded operators are implemented. However, they do not apply to the new and delete operators, which are covered separately in Chapter 4.

  • Operators must either be class member functions or take an argument that is of class or enumerated type or arguments that are references to class or enumerated types. For example:
    class Point
{
public:
    Point operator<( Point & );  // Declare a member operator
                                 //  overload.
    ...
    // Declare addition operators.
    friend Point operator+( Point&, int );
    friend Point operator+( int, Point& );
};

    The preceding code sample declares the less-than operator as a member function; however, the addition operators are declared as global functions that have friend access. Note that more than one implementation can be provided for a given operator. In the case of the preceding addition operator, the two implementations are provided to facilitate commutativity. It is just as likely that operators that add a Point to a Point, int to a Point, and so on, might be implemented.

  • Operators obey the precedence, grouping, and number of operands dictated by their typical use with built-in types. Therefore, there is no way to express the concept “add 2 and 3 to an object of type Point,” expecting 2 to be added to the x coordinate and 3 to be added to the y coordinate.

  • Unary operators declared as member functions take no arguments; if declared as global functions, they take one argument.

  • Binary operators declared as member functions take one argument; if declared as global functions, they take two arguments.

  • Overloaded operators cannot have default arguments.

  • All overloaded operators except assignment (operator=) are inherited by derived classes.

  • The first argument for member-function overloaded operators is always of the class type of the object for which the operator is invoked (the class in which the operator is declared, or a class derived from that class). No conversions are supplied for the first argument.

Note that the meaning of any of the operators can be changed completely. That includes the meaning of the address-of (&), assignment (=), and function-call operators. Also, identities that can be relied upon for built-in types can be changed using operator overloading. For example, the following four statements are usually equivalent when completely evaluated:

var = var + 1;
var += 1;
var++;
++var;

This identity cannot be relied upon for class types that overload operators. Moreover, some of the requirements implicit in the use of these operators for basic types are relaxed for overloaded operators. For example, the addition/assignment operator, +=, requires the left operand to be an l-value when applied to basic types; there is no such requirement when the operator is overloaded.

Note For consistency, it is often best to follow the model of the built-in types when defining overloaded operators. If the semantics of an overloaded operator differ significantly from its meaning in other contexts, it can be more confusing than useful.


C++ Unary Operators

The unary operators are shown in Table 12.4.

Table 12.4 Redefinable Unary Operators

Operator | Name
! | Logical NOT
& | Address-of
~ | One’s complement
* | Pointer dereference
+ | Unary plus
++ | Increment
– | Unary negation
–– | Decrement

Of the operators shown in Table 12.4, the postfix increment and decrement operators (++ and ––) are treated separately in Increment and Decrement.

To declare a unary operator function as a nonstatic member, you must declare it in the form:

ret-type operator op()

where ret-type is the return type and op is one of the operators listed in Table 12.4.

To declare a unary operator function as a global function, you must declare it in the form:

ret-type operator op( arg )

where ret-type and op are as described for member operator functions and the arg is an argument of class type on which to operate.

Note There is no restriction on the return types of the unary operators. For example, it makes sense for logical NOT (!) to return an integral value, but this is not enforced.


Increment and Decrement

The increment and decrement operators fall into a special category because there are two variants of each:

  • Preincrement and postincrement

  • Predecrement and postdecrement

When you write overloaded operator functions, it can be useful to implement separate versions for the prefix and postfix versions of these operators. To distinguish between the two, the following rule is observed: The prefix form of the operator is declared exactly the same way as any other unary operator; the postfix form accepts an additional argument of type int.

Important When specifying an overloaded operator for the postfix form of the increment or decrement operator, the additional argument must be of type int; specifying any other type generates an error.

The following example shows how to define prefix and postfix increment and decrement operators for the Point class:

class Point
{
public:
   // Declare prefix and postfix increment operators.
   Point& operator++();       // Prefix increment operator.
   Point operator++(int);     // Postfix increment operator.

   // Declare prefix and postfix decrement operators.
   Point& operator--();       // Prefix decrement operator.
   Point operator--(int);     // Postfix decrement operator.

   // Define default constructor.
   Point() { _x = _y = 0; }

   // Define accessor functions.
   int x() { return _x; }
   int y() { return _y; }
private:
   int _x, _y;
};

// Define prefix increment operator.
Point& Point::operator++()
{
   _x++;
   _y++;
   return *this;
}

// Define postfix increment operator.
Point Point::operator++(int)
{
   Point temp = *this;
   ++*this;
   return temp;
}

// Define prefix decrement operator.
Point& Point::operator--()
{
   _x--;
   _y--;
   return *this;
}

// Define postfix decrement operator.
Point Point::operator--(int)
{
   Point temp = *this;
   --*this;
   return temp;
}

The same operators can be defined in file scope (globally) using the following function heads:

friend Point& operator++( Point& )      // Prefix increment
friend Point& operator++( Point&, int ) // Postfix increment
friend Point& operator--( Point& )      // Prefix decrement
friend Point& operator--( Point&, int ) // Postfix decrement

The argument of type int that denotes the postfix form of the increment or decrement operator is not commonly used to pass arguments. It usually contains the value 0. However, it can be used as follows:

class Int
{
public:
    Int &operator++( int n );
private:
    int _i;
};

Int& Int::operator++( int n )
{
    if( n != 0 )    // Handle case where an argument is passed.
        _i += n;
    else
        _i++;       // Handle case where no argument is passed.
    return *this;
}
...

Int i;
i.operator++( 25 ); // Increment by 25.

There is no syntax for using the increment or decrement operators to pass these values other than explicit invocation, as shown in the preceding code. A more straightforward way to implement this functionality is to overload the addition/assignment operator (+=).


Binary Operators

Table 12.5 shows a list of operators that can be overloaded.

Table 12.5 Redefinable Binary Operators

Operator | Name
, | Comma
!= | Inequality
% | Modulus
%= | Modulus/assignment
& | Bitwise AND
&& | Logical AND
&= | Bitwise AND/assignment
* | Multiplication
*= | Multiplication/assignment
+ | Addition
+= | Addition/assignment
– | Subtraction
–= | Subtraction/assignment
–> | Member selection
–>* | Pointer-to-member selection
/ | Division
/= | Division/assignment
< | Less than
<< | Left shift
<<= | Left shift/assignment
<= | Less than or equal to
= | Assignment
== | Equality
> | Greater than
>= | Greater than or equal to
>> | Right shift
>>= | Right shift/assignment
^ | Exclusive OR
^= | Exclusive OR/assignment
| | Bitwise inclusive OR
|= | Bitwise inclusive OR/assignment
|| | Logical OR

To declare a binary operator function as a nonstatic member, you must declare it in the form:

ret-type operator op( arg )

where ret-type is the return type, op is one of the operators listed in Table 12.5, and arg is an argument of any type.

To declare a binary operator function as a global function, you must declare it in the form:

ret-type operator op( arg1, arg2 )

where ret-type and op are as described for member operator functions and arg1 and arg2 are arguments. At least one of the arguments must be of class type.

Note There is no restriction on the return types of the binary operators; however, most user-defined binary operators return either a class type or a reference to a class type.


Assignment

The assignment operator (=) is, strictly speaking, a binary operator. Its declaration is identical to any other binary operator, with the following exceptions:

  • It must be a nonstatic member function. No operator= can be declared as a nonmember function.

  • It is not inherited by derived classes.

  • A default operator= function can be generated by the compiler for class types if none exists. (For more information about default operator= functions, see Memberwise Assignment and Initialization in Chapter 11.)

The following example illustrates how to declare an assignment operator:

class Point
{
public:
    Point &operator=( Point & );  // Right side is the argument.
    ...
};

// Define assignment operator.
Point &Point::operator=( Point &ptRHS )
{
    _x = ptRHS._x;
    _y = ptRHS._y;

    return *this;  // Assignment operator returns left side.
}

Note that the supplied argument is the right side of the expression. The operator returns the object to preserve the behavior of the assignment operator, which returns the value of the left side after the assignment is complete. This allows writing statements such as:

pt1 = pt2 = pt3;


Function Call

The function-call operator, invoked using parentheses, is a binary operator. The syntax for a function call is:

Syntax

primary-expression ( expression-listopt )

In this context, primary-expression is the first operand, and expression-list, a possibly empty list of arguments, is the second operand. The function-call operator is used for operations that require a number of parameters. This works because expression-list is a list instead of a single operand. The function-call operator must be a nonstatic member function.

The function-call operator, when overloaded, does not modify how functions are called; rather, it modifies how the operator is to be interpreted when applied to objects of a given class type. For example, the following code would usually be meaningless:

Point pt;
pt( 3, 2 );

Given an appropriate overloaded function-call operator, however, this syntax can be used to offset the x coordinate 3 units and the y coordinate 2 units. The following code shows such a definition:

class Point
{
public:
    Point() { _x = _y = 0; }
    Point &operator()( int dx, int dy )
        { _x += dx; _y += dy; return *this; }
private:
    int _x, _y;
};

...

Point pt;
pt( 3, 2 );

Note that the function-call operator is applied to the name of an object, not the name of a function.


Subscripting

The subscript operator ([ ]), like the function-call operator, is considered a binary operator. The subscript operator must be a nonstatic member function that takes a single argument. This argument can be of any type and designates the desired array subscript.

The following example demonstrates how to create a vector of type int that implements bounds checking:

#include <iostream.h>

class IntVector
{
public:
   IntVector( int cElements );
   ~IntVector() { delete _iElements; }
   int& operator[]( int nSubscript );
private:
   int *_iElements;
   int _iUpperBound;
};

// Construct an IntVector.
IntVector::IntVector( int cElements )
{
   _iElements = new int[cElements];
   _iUpperBound = cElements;
}

// Subscript operator for IntVector.
int& IntVector::operator[]( int nSubscript )
{
   static int iErr = -1;

   if( nSubscript >= 0 && nSubscript < _iUpperBound )
      return _iElements[nSubscript];
   else
   {
      clog << "Array bounds violation." << endl;
      return iErr;
   }
}

// Test the IntVector class.
int main()
{
   IntVector v( 10 );

   for( int i = 0; i <= 10; ++i )
      v[i] = i;

   v[3] = v[9];

   for( i = 0; i <= 10; ++i )
      cout << "Element: [" << i << "] = " << v[i]
                << endl;

   return v[0];
}

When i reaches 10 in the preceding program, operator[] detects that an out-of-bounds subscript is being used and issues an error message.

Note that the function operator[] returns a reference type. This causes it to be an l-value, allowing you to use subscripted expressions on either side of assignment operators.


Class-Member Access

Class-member access can be controlled by overloading the member-selection operator (–>). This operator is considered a unary operator in this usage, and the overloaded operator function must be a class member function. Therefore, the declaration for such a function is:

class-type *operator–>()

where class-type is the name of the class to which this operator belongs. The member-selection operator function must be a nonstatic member function.

This operator is used (often in conjunction with the pointer-dereference operator) to implement “smart pointers” that validate pointers prior to dereference or count usage.

The . member-selector operator cannot be overloaded.


Grammar Summary

This appendix describes the formal grammar of the C++ language, as implemented in the Microsoft C++ compiler. It is loosely organized around the chapter organization of this book as follows:

  • The Keywords section describes keywords, covered in Chapter 1, Lexical Conventions.

  • The Expressions section describes the syntax of expressions, described in Chapter 4, Expressions.

  • The Declarations section describes the syntax of declarations, described in Chapter 6, Declarations.

  • The Declarators section describes the syntax of declarators, covered in Chapter 7, Declarators.

  • The Classes section covers the syntax used in declaring classes, as covered in Chapter 8, Classes.

  • The Statements section covers the syntax used in writing statements, as covered in Chapter 5, Statements.

  • The Microsoft Extensions section covers the syntax of features unique to Microsoft C++. Many of these features are covered in Appendix B, Microsoft-Specific Modifiers.


Grammar of C++ Keywords

class-name:

identifier

enum-name:

identifier

typedef-name:

identifier

identifier: one of

nondigit
identifier nondigit
identifier digit

nondigit: one of

_ a b c d e f g h i j k l m
n o p q r s t u v w x y z
A B C D E F G H I J K L M
N O P Q R S T U V W X Y Z

digit: one of

0 1 2 3 4 5 6 7 8 9


Grammar of C++ Expressions

expression:

assignment-expression
expression , assignment-expression

assignment-expression:

conditional-expression
unary-expression assignment-operator assignment-expression

assignment-operator: one of

= *= /= %= += –= >= <= &= ^= |=

conditional-expression:

logical-or-expression
logical-or-expression ? expression : conditional-expression

logical-or-expression:

logical-and-expression
logical-or-expression || logical-and-expression

logical-and-expression:

inclusive-or-expression
logical-and-expression && inclusive-or-expression

inclusive-or-expression:

exclusive-or-expression
inclusive-or-expression | exclusive-or-expression

exclusive-or-expression:

and-expression
exclusive-or-expression ^ and-expression

and-expression:

equality-expression
and-expression & equality-expression

equality-expression:

relational-expression
equality-expression == relational-expression
equality-expression != relational-expression

relational-expression:

shift-expression
relational-expression < shift-expression
relational-expression > shift-expression
relational-expression <= shift-expression
relational-expression => shift-expression

shift-expression:

additive-expression
shift-expression << additive-expression
shift-expression >> additive-expression

additive-expression:

multiplicative-expression
additive-expression + multiplicative-expression
additive-expression – multiplicative-expression

multiplicative-expression:

segment-expression
multiplicative-expression * segment-expression
multiplicative-expression / segment-expression
multiplicative-expression % segment-expression

segment-expression:

pm-expression
segment-expression :> pm-expression

pm-expression:

cast-expression
pm-expression .* cast-expression
pm-expression –>* cast-expression

cast-expression:

unary-expression
( type-name ) cast-expression

unary-expression:

postfix-expression
++ unary-expression
–– unary-expression
unary-operator cast-expression
sizeof unary-expression
sizeof ( type-name )
allocation-expression
deallocation-expression

unary-operator: one of

* & + – ! ~

allocation-expression:

::opt new placementopt new-type-name new-initializeropt
::opt new placementopt ( type-name ) new-initializeropt

placement:

( expression-list )

new-type-name:

type-specifier-list new-declaratoropt

new-declarator:

ms-modifier-list opt * cv-qualifier-list opt new-declaratoropt
ms-modifier-list opt complete-class-name :: *cv-qualifier-listopt
new-declaratoropt
new-declaratoropt [ expression ]

new-initializer:

( initializer-list )

deallocation-expression:

::opt delete cast-expression
::opt delete [ ] cast-expression

postfix-expression:

primary-expression
postfix-expression [ expression ]
postfix-expression ( expression-list )
simple-type-name ( expression-list )
postfix-expression . name
postfix-expression –> name
postfix-expression ++
postfix-expression ––
dynamic_cast < type-id > ( expression )
static_cast < type-id > ( expression )
const_cast < type-id > ( expression )
reinterpret_cast < type-id > ( expression )
typeid( expression )
typeid( type-id )

expression-list:

assignment-expression
expression-list , assignment-expression

primary-expression:

literal
this
:: identifier
:: operator-function-name
:: qualified-name ( expression )
name

name:

identifier
operator-function-name
conversion-function-name
~ class-name
qualified-name

qualified-name:

ms-modifier-listopt qualified-class-name :: name

literal:

integer-constant
character-constant
floating-constant
string-literal

integer-constant:

decimal-constant integer-suffixopt
octal-constant integer-suffixopt
hexadecimal-constant integer-suffixopt
'c-char-sequence'

decimal-constant:

nonzero-digit
decimal-constant digit

octal-constant:

0
octal-constant octal-digit

hexadecimal-constant:

0x hexadecimal-digit
0X hexadecimal-digit
hexadecimal-constant hexadecimal-digit

nonzero-digit: one of

1 2 3 4 5 6 7 8 9

octal-digit: one of

0 1 2 3 4 5 6 7

hexadecimal-digit: one of

0 1 2 3 4 5 6 7 8 9
a b c d e f
A B C D E F

integer-suffix:

unsigned-suffix long-suffixopt
long-suffix unsigned-suffixopt

unsigned-suffix: one of

u U

long-suffix: one of

l L

character-constant:

'c-char-sequence'
L'c-char-sequence'

c-char-sequence:

c-char
c-char-sequence c-char

c-char:

any member of the source character set except the single quote ('),
backslash (\), or newline character
escape-sequence

escape-sequence:

simple-escape-sequence
octal-escape-sequence
hexadecimal-escape-sequence

simple-escape-sequence: one of

\' \" \? \\
\a \b \f \n \r \t \v

octal-escape-sequence:

\ octal-digit
\ octal-digit octal-digit
\ octal-digit octal-digit octal-digit

hexadecimal-escape-sequence:

\x hexadecimal-digit
hexadecimal-escape-sequence hexadecimal-digit

floating-constant:

fractional-constant exponent-partopt floating-suffixopt
digit-sequence exponent-part floating-suffixopt

fractional-constant:

digit-sequenceopt . digit-sequence
digit-sequence .

exponent-part:

e signopt digit-sequence
E signopt digit-sequence

sign: one of

+ –

digit-sequence:

digit
digit-sequence digit

floating-suffix: one of

f l F L

string literal:

''s-char-sequence opt''
L ''s-char-sequence opt''

s-char-sequence:

s-char
s-char-sequence s-char

s-char:

any member of the source character set except double quotation marks ("), backslash (\), or newline character
escape-sequence


Grammar of C++ Declarations

declaration:

decl-specifiersopt declarator-listopt ;
asm-declaration
function-definition
linkage-specification
template-declaration:

asm-declaration:

__asm( string-literal );

decl-specifiers:

decl-specifiersopt decl-specifier

decl-specifier:

storage-class-specifier
type-specifier
fct-specifier
friend
typedef
__declspec ( extended-decl-modifier-seq )

storage-class-specifier:

auto
register
static
extern

fct-specifier:

inline
virtual

type-specifier:

simple-type-name
class-specifier
enum-specifier
elaborated-type-specifier
const
volatile

extended-decl-modifier-seq:

extended-decl-modifieropt
extended-decl-modifier extended-decl-modifier-seq

extended-decl-modifier:

thread
naked
dllimport
dllexport

simple-type-name:

complete-class-name
qualified-type-name
char
short
int
long
signed
unsigned
float
double
void

elaborated-type-specifier:

class-key identifier
class-key class-name
enum-name

class-key:

class
struct
union

qualified-type-name:

typedef-name
class-name :: qualified-type-name

complete-class-name:

qualified-class-name
:: qualified-class-name

qualified-class-name:

class-name
class-name :: qualified-class-name

enum-specifier:

enum identifieropt { enum-listopt }

enum-list:

enumerator
enum-list , enumerator

enumerator:

identifier
identifier = constant-expression

constant-expression:

conditional-expression

linkage-specification:

extern string-literal { declaration-listopt }
extern string-literal declaration

declaration-list:

declaration
declaration-list declaration

template-declaration:

template < template-argument-list > declaration

template-argument-list:

template-argument
template-argument-list , template-argument

template-argument:

type-argument
argument-declaration

type-argument:

class identifier

template-class-name:

template-name < template-arg-list >

template-arg-list:

template-arg
template-arg-list , template-arg

template-arg:

expression
type-name

original-namespace-name :

identifier

namespace-definition :

original-namespace-definition
extension-namespace-definition
unnamed-namespace-definition

original-namespace-definition :

namespace identifier { namespace-body }

extension-namespace-definition :

namespace original-namespace-name { namespace-body }

unnamed-namespace-definition :

namespace { namespace-body }

namespace-body :

declaration-seqopt

id-expression :

unqualified-id
qualified-id

nested-name-specifier :

class-or-namespace-name :: nested-name-specifieropt

class-or-namespace-name :

class-name
namespace-name

namespace-name :

original-namespace-name
namespace-alias

namespace-alias :

identifier

namespace-alias-definition :

namespace identifier = qualified-namespace-specifier;

qualified-namespace-specifier :

::opt nested-name-specifieropt class-or-namespace-name

using-declaration :

using ::opt nested-name-specifier unqualified-id
using :: unqualified-id

using-directive :

using namespace ::opt nested-name-specifieropt namespace-name


Grammar of C++ Declarators

declarator-list:

init-declarator
declarator-list , init-declarator

init-declarator:

ms-modifier-listopt declarator initializeropt

declarator:

dname
ptr-operator declarator
declarator ( argument-declaration-list ) cv-mod-listopt
declarator [ constant-expressionopt ]
( declarator )

cv-mod-list:

cv-qualifier cv-mod-listopt

ptr-operator:

ms-modifier-listopt * cv-qualifier-listopt
ms-modifier-listopt & cv-qualifier-listopt
ms-modifier-listopt complete-class-name :: * cv-qualifier-listopt

cv-qualifier-list:

cv-qualifier cv-qualifier-listopt

cv-qualifier:

const
volatile

dname:

name
class-name
~ class-name
typedef-name
qualified-type-name

type-name:

type-specifier-list ms-modifier-listopt abstract-declaratoropt

type-specifier-list:

type-specifier type-specifier-listopt

abstract-declarator:

ptr-operator ms-modifier-listopt abstract-declaratoropt
abstract-declaratoropt ( argument-declaration-list ) cv-qualifier-listopt
abstract-declaratoropt [ constant-expressionopt ]
( ms-modifier-listopt abstract-declarator )

argument-declaration-list:

arg-declaration-listopt . . .opt
arg-declaration-list , . . .

arg-declaration-list:

argument-declaration
arg-declaration-list , argument-declaration

argument-declaration:

decl-specifiers ms-modifier-listopt declarator
decl-specifiers ms-modifier-listopt declarator = expression
decl-specifiers ms-modifier-listopt abstract-declaratoropt
decl-specifiers ms-modifier-listopt abstract-declaratoropt = expression

function-definition:

decl-specifiersopt ms-modifier-listopt declarator ctor-initializeropt fct-body

fct-body:

compound-statement

initializer:

= expression
= { initializer-list ,opt }
( expression-list )

initializer-list:

expression
initializer-list , expression
{ initializer-list ,opt }


Grammar of Classes

class-specifier:

class-head { member-listopt }

class-head:

class-key ambient-modelopt identifieropt base-specopt
class-key ambient-modelopt class-name base-specopt

member-list:

member-declaration member-listopt
access-specifier : member-listopt

member-declaration:

decl-specifiersopt member-declarator-listopt ;
function-definition ;opt
qualified-name ;

member-declarator-list:

member-declarator
member-declarator-list , member-declarator

member-declarator:

ms-modifier-listopt declarator pure-specifieropt
identifieropt : constant-expression

pure-specifier:

= 0

base-spec:

: base-list

base-list:

base-specifier
base-list , base-specifier

base-specifier:

complete-class-name
virtual access-specifieropt complete-class-name
access-specifier virtualopt complete-class-name

access-specifier:

private
protected
public

conversion-function-name:

operator conversion-type-name

conversion-type-name:

type-specifier-list ptr-operatoropt

ctor-initializer:

: mem-initializer-list

mem-initializer-list:

mem-initializer
mem-initializer , mem-initializer-list

mem-initializer:

complete-class-name ( expression-listopt )
identifier ( expression-listopt )

operator-function-name:

operator operator

operator: one of

new delete
+ – * / % ^ & | ~
! = < > += –= *= /= %=
^= &= |= << >> >>= <<= == !=
<= >= && || ++ –– , –>* –>
() []


Grammar of C++ Statements

statement:

labeled-statement
expression-statement
compound-statement
selection-statement
iteration-statement
jump-statement
declaration-statement
asm-statement
try-except-statement
try-finally-statement

labeled-statement:

identifier : statement
case constant-expression : statement
default : statement

expression-statement:

expressionopt ;

compound-statement:

{ statement-listopt }

statement-list:

statement
statement-list statement

selection-statement:

if ( expression ) statement
if ( expression ) statement else statement
switch ( expression ) statement

iteration-statement:

while ( expression ) statement
do statement while ( expression ) ;
for ( for-init-statement expressionopt ; expressionopt ) statement

for-init-statement:

expression-statement
declaration-statement

jump-statement:

break ;
continue ;
return expressionopt ;
goto identifier ;

declaration-statement:

declaration

try-except-statement:

__try compound-statement
__except ( expression ) compound-statement

try-finally-statement:

__try compound-statement
__finally ( expression ) compound-statement


Microsoft Extensions

asm-statement:

__asm assembly-instruction ;opt
__asm { assembly-instruction-list } ;opt

assembly-instruction-list:

assembly-instruction ;opt
assembly-instruction ; assembly-instruction-list ;opt

ms-modifier-list:

ms-modifier ms-modifier-listopt

ms-modifier:

__cdecl
__fastcall
__stdcall
__syscall (reserved for future implementations)
__oldcall (reserved for future implementations)
__unaligned (reserved for future implementations)
based-modifier

based-modifier:

__based ( based-type )

based-type:

name


Microsoft-Specific Modifiers

Many of the Microsoft-specific keywords can be used to modify declarators to form derived types. (For more information about declarators, see Chapter 7, Declarators).

Table B.1 Microsoft-Specific Keywords

Keyword | Meaning | Used to Form Derived Types?
__asm | Insert the following assembly-language code. | No
__based | The name that follows declares a 32-bit offset to the 32-bit base contained in the declaration. | Yes
__cdecl | The name that follows uses the C naming and calling conventions. | Yes
__declspec | The name that follows (thread, naked, dllimport, or dllexport) specifies a Microsoft-specific storage-class attribute. | No
__fastcall | The name that follows declares a function that uses registers, when available, instead of the stack for argument passing. | Yes
__stdcall | The name that follows specifies a function that observes the standard calling convention. | Yes

The following sections discuss the syntactic usage and semantic meaning of the Microsoft-specific modifiers.


Based Addressing

This section includes the following topics:

  • __based

  • Based pointers

  • Pointers based on pointers


Using __based in 32-bit Compilations

Based addressing is useful when you need precise control over the segment in which objects are allocated (static and dynamic based data).

The only form of based addressing acceptable in 32-bit compilations is “based on a pointer” that defines a type that contains a 32-bit displacement to a 32-bit base or based on void.

Syntax

based-range-modifier :

__based ( base-expression )

base-expression :

based-variable
based-abstract-declarator
segment-name
segment-cast

based-variable :

identifier

based-abstract-declarator :

abstract-declarator

base-type :

type-name


Based Pointers

Pointers based on pointer addresses are the only form of the __based keyword valid in 32-bit compilations. In such compilations, based pointers are 32-bit offsets from a 32-bit base.

When dereferencing a based pointer, the base must be either explicitly specified or implicitly known through the declaration.


Pointers Based on Pointers

The “based on pointer” variant of based addressing enables specification of a pointer as a base-expression. The based pointer, then, is an offset into the segment starting at the beginning of the pointer on which it is based.

One use for pointers based on pointers is for persistent objects that contain pointers. A linked list of pointers based on pointers can be saved to disk and reloaded to another place in memory, and the pointers will still be valid. The following example declares such a linked list:

void *vpBuffer;

struct llist_t
{
  void __based( vpBuffer ) *vpData;
  llist_t __based( vpBuffer ) *llNext;
};

The pointer, vpBuffer, is assigned the address of memory allocated at some later point in the program; the linked list is then relocated relative to the value of vpBuffer.

Pointers based on pointer addresses are the only forms of __based valid in 32-bit compilations. In such compilations, they are 32-bit displacements from a 32-bit base.


Calling and Naming Convention Modifiers

Calling conventions determine how functions are called; naming conventions determine how external names are treated. For more information, see Calling Conventions Topics, in Visual C++ Programmer’s Guide.


C++ Extended Storage-Class Attributes

This section describes extended attribute syntax, which simplifies and standardizes extensions to the Microsoft C and C++ languages. The storage-class attributes that use extended attribute syntax include thread, naked, dllimport, and dllexport. Use of these attributes is described later in this section.


Extended Attribute Syntax

The extended attribute syntax for specifying storage-class information uses the __declspec keyword, which specifies that an instance of a given type is to be stored with a Microsoft-specific storage-class attribute (thread, naked, dllimport, dllexport, nothrow, property, selectany, or uuid). Examples of other storage-class modifiers include the static and extern keywords. However, these keywords are part of the ANSI specification of the C and C++ languages, and as such are not covered by extended attribute syntax.

This is the extended attribute syntax for C++:

Syntax

decl-specifier :

__declspec ( extended-decl-modifier-seq )

extended-decl-modifier-seq :

extended-decl-modifieropt
extended-decl-modifier extended-decl-modifier-seq

extended-decl-modifier :

thread
naked
dllimport
dllexport
nothrow
property
selectany
uuid(“ComObjectGUID”)

White space separates the declaration modifier sequence. Examples of the syntax appear in later sections.

The thread, naked, dllimport, dllexport, nothrow, property, selectany, and uuid storage-class attributes are properties only of the declaration of the object or function to which they are applied. Unlike the __near and __far keywords, which actually affect the type of object or function (in this case, 2- and 4-byte addresses), these storage-class attributes do not redefine the type attributes of the object itself. The thread attribute affects data and objects only. The naked attribute affects functions only. The dllimport and dllexport attributes affect functions, data, and objects. The property, selectany, and uuid attributes affect COM objects.


The thread Attribute

Thread Local Storage (TLS) is the mechanism by which each thread in a multithreaded process allocates storage for thread-specific data. In standard multithreaded programs, data is shared among all threads of a given process, whereas thread local storage is the mechanism for allocating per-thread data. For a complete discussion of threads, see Multithreading Topics, and see the API Programmer’s Reference in the Microsoft Win32® Software Development Kit.

The C and C++ languages include the extended storage-class attribute, thread. The thread attribute must be used with the __declspec keyword to declare a thread variable. For example, the following code declares an integer thread local variable and initializes it with a value:

__declspec( thread ) int tls_i = 1;

You must observe these guidelines when declaring thread local objects and variables:

  • You can apply the thread attribute only to data declarations and definitions, and classes that do not have member functions. It cannot be used on function declarations or definitions. For example, the following code generates a compiler error:
    #define Thread    __declspec( thread )
Thread void func();           // Error
  • You can specify the thread attribute only on data items with static storage duration. This includes global data objects (both static and extern), local static objects, and static data members of classes. You cannot declare automatic data objects with the thread attribute. For example, the following code generates compiler errors:
    #define Thread    __declspec( thread )
void func1()
{
    Thread int tls_i;            // Error
}

int func2( Thread int tls_i )    // Error
{
    return tls_i;
}
  • You must use the thread attribute for the declaration and the definition of a thread local object, whether the declaration and definition occur in the same file or separate files. For example, the following code generates an error:
    #define Thread    __declspec( thread )
extern int tls_i;      // This generates an error, because the
int Thread tls_i;      // declaration and the definition differ.
  • You cannot use the thread attribute as a type modifier. For example, the following code generates a compiler error:
    char __declspec( thread ) *ch;        // Error
  • Classes can be instantiated using thread only if they contain no member functions. The thread attribute is ignored if no object is declared as part of the class declaration. For example:
    __declspec(thread) class X {
public:
int I; } x;    // x is a thread object

X y;                // y is not a thread object

    Because the declaration of objects that use the thread attribute is permitted, these two examples are semantically equivalent:

    #define Thread    __declspec( thread )
Thread class B
{
// Code
} BObject;            // Okay--BObject declared thread local.

class B
{
// Code
}
Thread B BObject;     // Okay--BObject declared thread local.
  • Standard C permits initialization of an object or variable with an expression involving a reference to itself, but only for objects of nonstatic extent. Although C++ normally permits such dynamic initialization of an object with an expression involving a reference to itself, this type of initialization is not permitted with thread local objects. For example:
    #define Thread    __declspec( thread )
Thread int tls_i = tls_i;            // C and C++ error
int j = j;                           // Okay in C++; C error
Thread int tls_i = sizeof( tls_i )   // Okay in C and C++

    Note that a sizeof expression that includes the object being initialized does not constitute a reference to itself and is allowed in C and C++.


The naked Attribute

For functions declared with the naked attribute, the compiler generates code without prolog and epilog code. You can use this feature to write your own prolog/epilog code sequences using inline assembler code. Naked functions are particularly useful in writing virtual device drivers.

Because the naked attribute is only relevant to the definition of a function and is not a type modifier, naked functions use the extended attribute syntax, described previously. For example, this code defines a function with the naked attribute:

__declspec( naked ) int func( formal_parameters )
{
   // Function body
}

Or, alternatively:

#define Naked   __declspec( naked )
Naked int func( formal_parameters )
{
   // Function body
}

The naked attribute affects only the nature of the compiler’s code generation for the function’s prolog and epilog sequences. It does not affect the code that is generated for calling such functions. Thus, the naked attribute is not considered part of the function’s type, and function pointers cannot have the naked attribute. Furthermore, the naked attribute cannot be applied to a data definition. For example, this code sample generates an error:

__declspec( naked ) int i;       // Error--naked attribute not
                                 // permitted on data declarations.

The naked attribute is relevant only to the definition of the function and cannot be specified in the function’s prototype. For example, this declaration generates a compiler error:

__declspec( naked ) int func();  // Error--naked attribute not
                                 // permitted on function declarations


Rules and Limitations

  • The return statement is not permitted in a naked function. However, you can return an int by moving the return value into the EAX register before the RET instruction.

  • Structured exception handling constructs are not permitted in a naked function, because the constructs must unwind across the stack frame.

  • The setjmp run-time function cannot be used in a naked function, because it too must unwind across the stack frame. However, use of the longjmp run-time function is permitted.

  • Use of the _alloca function is not permitted in a naked function.

  • To ensure that no initialization code for local variables appears before the prolog sequence, initialized local variables are not permitted at function scope. In particular, the declaration of C++ objects is not permitted at function scope. There can, however, be initialized data in a nested scope.

  • Frame pointer optimization (the /Oy compiler option) is not recommended, but it is automatically suppressed for a naked function.


Considerations for Writing Prolog/Epilog Code

Before writing your own prolog and epilog code sequences, it is important to understand how the stack frame is laid out. It is also useful to know how to use the __LOCAL_SIZE symbol.

C++ Stack Frame Layout

This example shows the standard prolog code that might appear in a 32-bit function:

push        ebp                ; Save ebp
mov         ebp, esp           ; Set stack frame pointer
sub         esp, localbytes    ; Allocate space for locals
push        <registers>        ; Save registers

The localbytes variable represents the number of bytes needed on the stack for local variables, and the <registers> variable is a placeholder that represents the list of registers to be saved on the stack. After pushing the registers, you can place any other appropriate data on the stack. The following is the corresponding epilog code:

pop         <registers>   ; Restore registers
mov         esp, ebp      ; Restore stack pointer
pop         ebp           ; Restore ebp
ret                       ; Return from function

The stack always grows down (from high to low memory addresses). The base pointer (ebp) points to the pushed value of ebp. The locals area begins at ebp-2. To access local variables, calculate an offset from ebp by subtracting the appropriate value from ebp.

__LOCAL_SIZE

The compiler provides a symbol, __LOCAL_SIZE, for use in the inline assembler block of function prolog code. This symbol is used to allocate space for local variables on the stack frame in custom prolog code.

The compiler determines the value of __LOCAL_SIZE. Its value is the total number of bytes of all user-defined local variables and compiler-generated temporary variables. __LOCAL_SIZE can be used only as an immediate operand; it cannot be used in an expression. You must not change or redefine the value of this symbol. For example:

mov        eax, __LOCAL_SIZE           ;Immediate operand--Okay
mov        eax, [ebp - __LOCAL_SIZE]   ;Error

The following example of a naked function containing custom prolog and epilog sequences uses the __LOCAL_SIZE symbol in the prolog sequence:

__declspec ( naked ) func()
{
   int i;
   int j;

   __asm      /* prolog */
      {
      push   ebp
      mov      ebp, esp
      sub      esp, __LOCAL_SIZE
      }

   /* Function body */

   __asm      /* epilog */
      {
      mov      esp, ebp
      pop      ebp
      ret
      }
}


The dllexport and dllimport Attributes

The dllexport and dllimport storage-class modifiers export and import functions, data, and objects to and from a DLL. These modifiers, or attributes, explicitly define the DLL’s interface to its client, which can be the executable file or another DLL. Declaring functions as dllexport eliminates the need for a module-definition (.DEF) file, at least with respect to the specification of exported functions. Note that dllexport replaces the __export keyword.

The declaration of dllexport and dllimport uses extended attribute syntax:

__declspec( dllexport ) void func();

Alternatively, to make your code more readable, you can use macro definitions:

#define DllImport   __declspec( dllimport )
#define DllExport   __declspec( dllexport )

DllExport void func();
DllExport int i = 10;
DllImport int j;
DllExport int n;


Definitions and Declarations

The DLL interface refers to all items (functions and data) that are known to be exported by some program in the system; that is, all items that are declared as dllimport or dllexport. All declarations included in the DLL interface must specify either the dllimport or dllexport attribute. However, the definition must specify only the dllexport attribute. For example, the following function definition generates a compiler error:

__declspec( dllimport ) int func()  // Error; dllimport
                                    // prohibited on definition.
{
   return 1;
}

This code also generates an error:

#define DllImport   __declspec( dllimport )

__declspec( dllimport ) int i = 10;  // Error; this is a
                                     // definition.

However, this is correct syntax:

__declspec( dllexport ) int i = 10;     // Okay--export definition

The use of dllexport implies a definition, while dllimport implies a declaration. You must use the extern keyword with dllexport to force a declaration; otherwise, a definition is implied. Thus, the following examples are correct:

#define DllImport   __declspec( dllimport )
#define DllExport   __declspec( dllexport )

extern DllImport int k; // These are both correct and imply a
DllImport int j;        // declaration.

The following examples clarify the preceding:

static __declspec( dllimport ) int l; // Error; not declared extern.

void func()
{
    static __declspec( dllimport ) int s;  // Error; not declared
                                           // extern.
    __declspec( dllimport ) int m;         // Okay; this is a
                                           // declaration.
    __declspec( dllexport ) int n;         // Error; implies external
                                           // definition in local scope.
    extern __declspec( dllimport ) int i;  // Okay; this is a
                                           // declaration.
    extern __declspec( dllexport ) int k;  // Okay; extern implies
                                           // declaration.
    __declspec( dllexport ) int x = 5;     // Error; implies external
                                           // definition in local scope.
}


Defining Inline C++ Functions with dllexport and dllimport

You can define as inline a function with the dllexport attribute. In this case, the function is always instantiated and exported, whether or not any module in the program references the function. The function is presumed to be imported by another program.

You can also define as inline a function declared with the dllimport attribute. In this case, the function can be expanded (subject to /Ob specifications), but never instantiated. In particular, if the address of an inline imported function is taken, the address of the function residing in the DLL is returned. This behavior is the same as taking the address of a non-inline imported function.

These rules apply to inline functions whose definitions appear within a class definition. In addition, static local data and strings in inline functions maintain the same identities between the DLL and client as they would in a single program (that is, an executable file without a DLL interface).

Exercise care when providing imported inline functions. For example, if you update the DLL, don’t assume that the client will use the changed version of the DLL. To ensure that you are loading the proper version of the DLL, rebuild the DLL’s client as well.


General Rules and Limitations

  • If you declare a function or object without the dllimport or dllexport attribute, the function or object is not considered part of the DLL interface. Therefore, the definition of the function or object must be present in that module or in another module of the same program. To make the function or object part of the DLL interface, you must declare the definition of the function or object in the other module as dllexport. Otherwise, a linker error is generated.

    If you declare a function or object with the dllexport attribute, its definition must appear in some module of the same program. Otherwise, a linker error is generated.

  • If a single module in your program contains both dllimport and dllexport declarations for the same function or object, the dllexport attribute takes precedence over the dllimport attribute. However, a compiler warning is generated. For example:
    __declspec( dllimport ) int i;
__declspec( dllexport ) int i;   // Warning; inconsistent;
                                 // dllexport takes precedence.
  • In C++, you can initialize a globally declared or static local data pointer or with the address of a data object declared with the dllimport attribute, which generates an error in C. In addition, you can initialize a static local function pointer with the address of a function declared with the dllimport attribute. In C, such an assignment sets the pointer to the address of the DLL import thunk (a code stub that transfers control to the function) rather than the address of the function. In C++, it sets the pointer to the address of the function. For example:
    __declspec( dllimport ) void func1( void );
__declspec( dllimport ) int i;

int *pi = &i;                             // Error in C
static void ( *pf )( void ) = &func1;     // Address of thunk in C,
                                          // function in C++

void func2()
{
static int *pi = &i;                  // Error in C
static void ( *pf )( void ) = &func1; // Address of thunk in C,
                                         // function in C++
}

    However, because a program that includes the dllexport attribute in the declaration of an object must provide the definition for that object somewhere in the program, you can initialize a global or local static function pointer with the address of a dllexport function. Similarly, you can initialize a global or local static data pointer with the address of a dllexport data object. For example, the following code does not generate errors in C or C++:

    __declspec( dllexport ) void func1( void );
__declspec( dllexport ) int i;

int *pi = &i;                              // Okay
static void ( *pf )( void ) = &func1;      // Okay

void func2()
{
    static int *pi = &i;                   // Okay
    static void ( *pf )( void ) = &func1;  // Okay
}


Using dllimport and dllexport in C++

You can declare C++ classes with the dllimport or dllexport attribute. These forms imply that the entire class is imported or exported. Classes exported this way are called exportable classes.

The following example defines an exportable class. All its member functions and static data are exported:

#define DllExport   __declspec( dllexport )

class DllExport C
{
   int i;
   virtual int func( void )
   { return 1; }
};

Note that explicit use of the dllimport and dllexport attributes on members of an exportable class is prohibited.


dllexport Classes

When you declare a class dllexport, all its member functions and static data members are exported. You must provide the definitions of all such members in the same program. Otherwise, a linker error is generated. The one exception to this rule applies to pure virtual functions, for which you need not provide explicit definitions. However, because a destructor for an abstract class is always called by the destructor for the base class, pure virtual destructors must always provide a definition. Note that these rules are the same for nonexportable classes.

If you export data of class type or functions that return classes, be sure to export the class.


dllimport Classes

When you declare a class dllimport, all its member functions and static data members are imported. Unlike the behavior of dllimport and dllexport on nonclass types, static data members cannot specify a definition in the same program in which a dllimport class is defined.


Inheritance and Exportable Classes

All base classes of an exportable class must be exportable. If not, a compiler warning is generated. Moreover, all accessible members that are also classes must be exportable. This rule permits a dllexport class to inherit from a dllimport class, and a dllimport class to inherit from a dllexport class (though the latter is not recommended). As a rule, everything that is accessible to the DLL’s client (according to C++ access rules) should be part of the exportable interface. This includes private data members referenced in inline functions.


Selective Member Import/Export

Because member functions and static data within a class implicitly have external linkage, you can declare them with the dllimport or dllexport attribute, unless the entire class is exported. If the entire class is imported or exported, the explicit declaration of member functions and data as dllimport or dllexport is prohibited. If you declare a static data member within a class definition as dllexport, a definition must occur somewhere within the same program (as with nonclass external linkage).

Similarly, you can declare member functions with the dllimport or dllexport attributes. In this case, you must provide a dllexport definition somewhere within the same program.

It is worthwhile to note several important points regarding selective member import and export:

  • Selective member import/export is best used for providing a version of the exported class interface that is more restrictive; that is, one for which you can design a DLL that exposes fewer public and private features than the language would otherwise allow. It is also useful for fine-tuning the exportable interface: when you know that the client, by definition, is unable to access some private data, you need not export the entire class.

  • If you export one virtual function in a class, you must export all of them, or at least provide versions that the client can use directly.

  • If you have a class in which you are using selective member import/export with virtual functions, the functions must be in the exportable interface or defined inline (visible to the client).

  • If you define a member as dllexport but do not include it in the class definition, a compiler error is generated. You must define the member in the class header.

  • Although the definition of class members as dllimport or dllexport is permitted, you cannot override the interface specified in the class definition.

  • If you define a member function in a place other than the body of the class definition in which you declared it, a warning is generated if the function is defined as dllexport or dllimport (if this definition differs from that specified in the class declaration).


C++ Inline Assembler

The inline assembler lets you embed assembly-language instructions in your C source programs without extra assembly and link steps. The inline assembler is built into the compiler—you don’t need a separate assembler such as the Microsoft Macro Assembler (MASM).

Because the inline assembler doesn’t require separate assembly and link steps, it is more convenient than a separate assembler. Inline assembly code can use any C variable or function name that is in scope, so it is easy to integrate it with your program’s C code. And because the assembly code can be mixed with C statements, it can do tasks that are cumbersome or impossible in C alone.

The __asm keyword invokes the inline assembler and can appear wherever a C statement is legal. It cannot appear by itself. It must be followed by an assembly instruction, a group of instructions enclosed in braces, or, at the very least, an empty pair of braces. The term “__asm block” here refers to any instruction or group of instructions, whether or not in braces.

The following code is a simple __asm block enclosed in braces. (The code is a custom function prolog sequence.)

__asm
{
   push ebp
   mov  ebp, esp
   sub  esp, __LOCAL_SIZE
}

Alternatively, you can put __asm in front of each assembly instruction:

__asm push ebp
__asm mov  ebp, esp
__asm sub  esp, __LOCAL_SIZE

Since the __asm keyword is a statement separator, you can also put assembly instructions on the same line:

__asm push ebp   __asm mov  ebp, esp   __asm sub  esp, __LOCAL_SIZE


Compiler COM Support Classes

Microsoft Specific

Standard classes are used to support some of the COM types. The classes are defined in COMDEF.H and the header files generated from the type library.

#include <comdef.h>

Class | Purpose
_com_error | Defines the error object thrown by _com_raise_error in most failures.
_com_ptr_t | Encapsulates COM interface pointers, and automates the required calls to AddRef, Release, and QueryInterface.
_bstr_t | Wraps the BSTR type to provide useful operators and methods.
_variant_t | Wraps the VARIANT type to provide useful operators and methods.

In addition, there is a support routine called _com_raise_error, which is used by all compiler-generated COM support code to throw a _com_error in response to a failure

_com_raise_error is defined in comdef.h as,

void __stdcall _com_raise_error(HRESULT hr, IErrorInfo* perrinfo = 0) throw(_com_error);

The actual source code is,

void __stdcall _com_raise_error(HRESULT hr, IErrorInfo* perrinfo) throw(_com_error)
{
   throw _com_error(hr, perrinfo);
}

_com_raise_error can be replaced by a user-written version of the same name and prototype. This could be done if you want to use #import, but don't want to use C++ exception handling. In that case, a user version of _com_raise_error might decide to do a longjmp or pop up a message box and halt. The user version should not return, though, since the compiler COM support code does not expect it to return.

END Microsoft Specific


_com_error

Microsoft Specific

A _com_error object represents an exception condition detected by the error-handling wrapper functions in the header files generated from the type library or by one of the COM support classes. The _com_error class encapsulates the HRESULT error code and any associated IErrorInfo object.

#include <comdef.h>

Compiler COM Support Class Overview

Construction

_com_error Constructs a _com_error object.

Operators

operator = Assigns an existing _com_error object to another.

Extractor Functions

Error | Retrieves the HRESULT passed to the constructor.
ErrorInfo | Retrieves the IErrorInfo object passed to the constructor.
WCode | Retrieves the 16-bit error code mapped into the encapsulated HRESULT.

IErrorInfo functions

Description | Calls IErrorInfo::GetDescription function.
HelpContext | Calls IErrorInfo::GetHelpContext function.
HelpFile | Calls IErrorInfo::GetHelpFile function
Source | Calls IErrorInfo::GetSource function.
GUID | Calls IErrorInfo::GetGUID function.

Format Message Extractor

ErrorMessage Retrieves the string message for HRESULT stored in the _com_error object.

ExepInfo.wCode to HRESULT Mappers

HRESULTToWCode | Maps 32-bit HRESULT to 16-bit wCode.
WCodeToHRESULT | Maps 16-bit wCode to 32-bit HRESULT.

END Microsoft Specific


Member Functions


_com_error::_com_error

Microsoft Specific

_com_error( HRESULT hr, IErrorInfo* perrinfo = NULL ) throw( );

_com_error( const _com_error& that ) throw( );

Parameters

hr

HRESULT information

perrinfo

IErrorInfo object

that

An existing _com_error object

Remarks

Constructs a _com_error object. The first constructor creates a new object given an HRESULT and optional IErrorInfo object. The second creates a copy of an existing _com_error object.

_com_error Overview

END Microsoft Specific


_com_error::Description

Microsoft Specific

_bstr_t Description( ) const throw ( );

Return Value

Returns the result of IErrorInfo::GetDescription for the IErrorInfo object recorded within the _com_error object. The resulting BSTR is encapsulated in a _bstr_t object. If no IErrorInfo is recorded, it returns an empty _bstr_t.

Remarks

Calls the IErrorInfo::GetDescription function and retrieves IErrorInfo recorded within the _com_error object. Any failure while calling the IErrorInfo::GetDescription method is ignored.

_com_error Overview

END Microsoft Specific


_com_error::Error

Microsoft Specific

HRESULT Error( ) const throw( );

Return Value

Raw HRESULT item passed into the constructor.

Remarks

Retrieves the encapsulated HRESULT item in a _com_error object.

_com_error Overview

END Microsoft Specific


_com_error::ErrorInfo

Microsoft Specific

IErrorInfo * ErrorInfo( ) const throw( );

Return Value

Raw IErrorInfo item passed into the constructor.

Remarks

Retrieves the encapsulated IErrorInfo item in a _com_error object, or NULL if no IErrorInfo item is recorded. The caller must call Release on the returned object when finished using it.

_com_error Overview

END Microsoft Specific


_com_error::ErrorMessage

Microsoft Specific

const TCHAR * ErrorMessage( ) const throw( );

Return Value

Returns the string message for the HRESULT recorded within the _com_error object. If the HRESULT is a mapped 16-bit wCode, then a generic message “IDispatch error #<wCode>” is returned. If no message is found, then a generic message “Unknown error #<hresult>” is returned. The returned string is either a Unicode or multibyte string, depending on the state of the _UNICODE macro.

Remarks

Retrieves the appropriate system message text for HRESULT recorded within the _com_error object. The system message text is obtained by calling the Win32 FormatMessage function. The string returned is allocated by the FormatMessage API, and it is released when the _com_error object is destroyed.

_com_error Overview

END Microsoft Specific


_com_error::GUID

Microsoft Specific

GUID GUID( ) const throw( );

Return Value

Returns the result of IErrorInfo::GetGUID for the IErrorInfo object recorded within the _com_error object. If no IErrorInfo object is recorded, it returns GUID_NULL.

Remarks

Calls the IErrorInfo::GetGUID method. Any failure while calling the IErrorInfo::GetGUID method is ignored.

_com_error Overview

END Microsoft Specific


_com_error::HelpContext

Microsoft Specific

DWORD HelpContext( ) const throw( );

Return Value

Returns the result of IErrorInfo::GetHelpContext for the IErrorInfo object recorded within the _com_error object. If no IErrorInfo object is recorded, it returns a zero.

Remarks

Calls the IErrorInfo::GetHelpContext interface method. Any failure while calling the IErrorInfo::GetHelpContext method is ignored.

_com_error Overview

END Microsoft Specific


_com_error::HelpFile

Microsoft Specific

_bstr_t HelpFile( ) const throw( );

Return Value

Returns the result of IErrorInfo::GetHelpFile for the IErrorInfo object recorded within the _com_error object. The resulting BSTR is encapsulated in a _bstr_t object. If no IErrorInfo is recorded, it returns an empty _bstr_t.

Remarks

Calls the IErrorInfo::GetHelpFile interface method. Any failure while calling the IErrorInfo::GetHelpFile method is ignored.

_com_error Overview

END Microsoft Specific


_com_error::HRESULTToWCode

Microsoft Specific

static WORD HRESULTToWCode( HRESULT hr ) throw( );

Return Value

16-bit wCode mapped from the 32-bit HRESULT

Parameters

hr

The 32-bit HRESULT to be mapped to 16-bit wCode

Remarks

Performs 32-bit HRESULT to 16-bit wCode mapping. See _com_error::WCode for more information.

See Also _com_error::WCode, _com_error::WCodeToHRESULT, _com_error Overview

END Microsoft Specific


_com_error::Source

Microsoft Specific

_bstr_t Source( ) const throw( );

Return Value

Returns the result of IErrorInfo::GetSource for the IErrorInfo object recorded within the _com_error object. The resulting BSTR is encapsulated in a _bstr_t object. If no IErrorInfo is recorded, it returns an empty _bstr_t.

Remarks

Calls the IErrorInfo::GetSource interface method. Any failure while calling the IErrorInfo::GetSource method is ignored.

_com_error Overview

END Microsoft Specific


_com_error::WCode

Microsoft Specific

WORD WCode ( ) const throw( );

Return Value

If the HRESULT is within the range 0x80040200 to 0x8004FFFF, the WCode method returns the HRESULT minus 0x80040200, else it returns zero.

Remarks

The WCode method retrieves a 16-bit error code which has been mapped into the encapsulated HRESULT.

The WCode method is used to undo a mapping which happens in the COM support code. The wrapper for a dispinterface property or method calls a support routine which packages the arguments and calls IDispatch::Invoke. Upon return, if a failure HRESULT of DISP_E_EXCEPTION is returned, the error information is retrieved from the EXCEPINFO structure passed to IDispatch::Invoke. The error code can either be a 16-bit value stored in the wCode member of the EXCEPINFO structure or a full 32-bit value in the scode member of the EXCEPINFO structure. If a 16-bit wCode is returned, it must first be mapped to a 32-bit failure HRESULT.

See Also _com_error::HRESULTToWCode, _com_error::WCodeToHRESULT, _com_error Overview

END Microsoft Specific


_com_error::WCodeToHRESULT

Microsoft Specific

static HRESULT WCodeToHRESULT( WORD wCode ) throw( );

Return Value

32-bit HRESULT mapped from the 16-bit wCode.

Parameters

wCode

The 16-bit wCode to be mapped to 32-bit HRESULT

Remarks

Performs 16-bit wCode to 32-bit HRESULT mapping. See the WCode member function.

See Also _com_error::WCode, _com_error::HRESULTToWCode, _com_error Overview

END Microsoft Specific


Operators


_com_error::operator =

Microsoft Specific

_com_error& operator = ( const _com_error& that ) throw ( );

Parameters

that

A _com_error object

Remarks

Assigns an existing _com_error object to another.

_com_error Overview

END Microsoft Specific


_com_ptr_t

Microsoft Specific

A _com_ptr_t object encapsulates a COM interface pointer and is called a “smart” pointer. This template class manages resource allocation and deallocation, via function calls to the IUnknown member functions: QueryInterface, AddRef, and Release.

A smart pointer is usually referenced by the typedef definition provided by the _COM_SMARTPTR_TYPEDEF macro. This macro takes an interface name and the IID, and declares a specialization of _com_ptr_t with the name of the interface plus a suffix of Ptr. For example,

_COM_SMARTPTR_TYPEDEF(IMyInterface, __uuidof(IMyInterface));

declares the _com_ptr_t specialization IMyInterfacePtr.

A set of function templates, not members of this template class, support comparisons with a smart pointer on the right-hand side of the comparison operator.

#include <comdef.h>

Compiler COM Support Class Overview

Construction

_com_ptr_t Constructs a _com_ptr_t object.

Low-level Operations

AddRef | Calls the AddRef member function of IUnknown on the encapsulated interface pointer.
Attach | Encapsulates a raw interface pointer of this smart pointer’s type.
CreateInstance | Creates a new instance of an object given a CLSID or ProgID.
Detach | Extracts and returns the encapsulated interface pointer.
GetActiveObject | Attaches to an existing instance of an object given a CLSID or ProgID.
GetInterfacePtr | Returns the encapsulated interface pointer.
QueryInterface | Calls the QueryInterface member function of IUnknown on the encapsulated interface pointer.
Release | Calls the Release member function of IUnknown on the encapsulated interface pointer.

Operators

operator = | Assigns a new value to an existing _com_ptr_t object.
operators ==, !=, <, >, <=, >= | Compare the smart pointer object to another smart pointer, raw interface pointer, or NULL.
Extractors | Extract the encapsulated COM interface pointer.

END Microsoft Specific


_com_ptr_t::_com_ptr_t

Microsoft Specific

_com_ptr_t( ) throw( );

_com_ptr_t( Interface* pInterface ) throw( );

_com_ptr_t( Interface* pInterface, bool fAddRef ) throw( );

_com_ptr_t( int NULL ) throw( _com_error );

template< > _com_ptr_t( const _com_ptr_t& cp ) throw( );

template<typename _InterfacePtr> _com_ptr_t( const _InterfacePtr& p ) throw( _com_error );

template< > _com_ptr_t( const _variant_t& varSrc ) throw( _com_error );

explicit _com_ptr_t( const CLSID& clsid, DWORD dwClsContext = CLSCTX_ALL) throw( _com_error );

explicit _com_ptr_t( LPOLESTR lpOleStr, DWORD dwClsContext = CLSCTX_ALL) throw( _com_error );

explicit _com_ptr_t( LPCSTR lpcStr, DWORD dwClsContext = CLSCTX_ALL ) throw( _com_error );

Parameters

pInterface

a raw interface pointer

fAddRef

if true, AddRef is called to increment the reference count of the encapsulated interface pointer

cp

a _com_ptr_t object

p

a raw interface pointer, its type being different from the smart pointer type of this _com_ptr_t object

varSrc

a _variant_t object

clsid

the CLSID of a coclass

dwClsContext

context for running executable code

lpOleStr

a Unicode string that holds either a CLSID (starting with “{“) or a ProgID

lpcStr

a multibyte string that holds either a CLSID (starting with “{“) or a ProgID.

Remarks

Constructs a _com_ptr_t object.

  • _com_ptr_t( ) Constructs a NULL smart pointer.

  • _com_ptr_t( pInterface ) Constructs a smart pointer from a raw interface pointer of this smart pointer’s type. AddRef is called to increment the reference count for the encapsulated interface pointer.

  • _com_ptr_t( pInterface, fAddRef ) Constructs a smart pointer from a raw interface pointer of this smart pointer’s type. If fAddRef is true, AddRef is called to increment the reference count for the encapsulated interface pointer. If fAddRef is false, this constructor takes ownership of the raw interface pointer without calling AddRef.

  • _com_ptr_t( NULL ) Constructs a NULL smart pointer. The NULL argument must be a zero.

  • _com_ptr_t( cp ) Constructs a smart pointer as a copy of another instance of the same smart pointer. AddRef is called to increment the reference count for the encapsulated interface pointer.

  • _com_ptr_t( p ) Constructs a smart pointer from a different smart pointer type or from a different raw interface pointer. QueryInterface is called to find an interface pointer of this smart pointer’s type. If QueryInterface fails with an E_NOINTERFACE error, a NULL smart pointer is constructed. Any other error causes a _com_error to be raised.

  • _com_ptr_t( varSrc ) Constructs a smart pointer from a _variant_t object. The encapsulated VARIANT must be of type VT_DISPATCH or VT_UNKNOWN, or it can be converted into one of these two types. If QueryInterface fails with an E_NOINTERFACE error, a NULL smart pointer is constructed. Any other error causes a _com_error to be raised.

  • _com_ptr_t( clsid, dwClsContext ) Constructs a smart pointer given the CLSID of a coclass. This function calls CoCreateInstance, by the member function CreateInstance, to create a new COM object and then queries for this smart pointer’s interface type. If QueryInterface fails with an E_NOINTERFACE error, a NULL smart pointer is constructed. Any other error causes a _com_error to be raised.

  • _com_ptr_t( lpOleStr, dwClsContext ) Constructs a smart pointer given a Unicode string which holds either a CLSID (starting with “{“) or a ProgID. This function calls CoCreateInstance, by the member function CreateInstance, to create a new COM object and then queries for this smart pointer’s interface type. If QueryInterface fails with an E_NOINTERFACE error, a NULL smart pointer is constructed. Any other error causes a _com_error to be raised.

  • _com_ptr_t( lpcStr, dwClsContext ) Constructs a smart pointer given a multibyte character string which holds either a CLSID (starting with “{“) or a ProgID. This function calls CoCreateInstance, by the member function CreateInstance, to create a new COM object and then queries for this smart pointer’s interface type. If QueryInterface fails with an E_NOINTERFACE error, a NULL smart pointer is constructed. Any other error causes a _com_error to be raised.

_com_ptr_t Overview

END Microsoft Specific


_com_ptr_t::AddRef

Microsoft Specific

void AddRef( ) throw( _com_error );

Remarks

Calls IUnknown::AddRef on the encapsulated interface pointer, raising an E_POINTER error if the pointer is NULL.

_com_ptr_t Overview

END Microsoft Specific


_com_ptr_t::Attach

Microsoft Specific

void Attach( Interface* pInterface ) throw( );

void Attach( Interface* pInterface, bool fAddRef ) throw( );

Parameters

pInterface

a raw interface pointer

fAddRef

If it is true, then AddRef is called. If it is false, the _com_ptr_t object takes ownership of the raw interface pointer without calling AddRef.

Remarks

Encapsulates a raw interface pointer of this smart pointer’s type.

  • Attach( pInterface ) AddRef is not called. The ownership of the interface is passed to this _com_ptr_t object. Release is called to decrement the reference count for the previously encapsulated pointer.

  • Attach( pInterface, fAddRef ) If fAddRef is true, AddRef is called to increment the reference count for the encapsulated interface pointer. If fAddRef is false, this _com_ptr_t object takes ownership of the raw interface pointer without calling AddRef. Release is called to decrement the reference count for the previously encapsulated pointer.

_com_ptr_t Overview

END Microsoft Specific


_com_ptr_t::CreateInstance

Microsoft Specific

HRESULT CreateInstance( const CLSID& rclsid, IUnknown* pOuter=NULL, DWORD dwClsContext = CLSCTX_ALL ) throw( );

HRESULT CreateInstance( LPOLESTR clsidString, IUnknown* pOuter=NULL, DWORD dwClsContext = CLSCTX_ALL ) throw( );

HRESULT CreateInstance( LPCSTR clsidStringA, IUnknown* pOuter=NULL, DWORD dwClsContext = CLSCTX_ALL ) throw( );

Parameters

rclsid

the CLSID of an object

clsidString

a Unicode string that holds either a CLSID (starting with “{“) or a ProgID

clsidStringA

a multibyte string that holds either a CLSID (starting with “{“) or a ProgID

dwClsContext

context for running executable code

pOuter

the outer unknown for aggregation

Remarks

Creates a new running instance of an object given a CLSID or ProgID. These member functions call CoCreateInstance to create a new COM object and then queries for this smart pointer’s interface type. The resulting pointer is then encapsulated within this _com_ptr_t object. Release is called to decrement the reference count for the previously encapsulated pointer. This routine returns the HRESULT to indicate success or failure.

  • CreateInstance( rclsid, dwClsContext ) Creates a new running instance of an object given a CLSID.

  • CreateInstance( clsidString, dwClsContext ) Creates a new running instance of an object given a Unicode string which holds either a CLSID (starting with “{“) or a ProgID.

  • CreateInstance( clsidStringA, dwClsContext ) Creates a new running instance of an object given a multibyte character string which holds either a CLSID (starting with “{“) or a ProgID. Calls MultiByteToWideChar, which assumes that the string is in the ANSI code page rather than an OEM code page.

_com_ptr_t Overview

END Microsoft Specific


_com_ptr_t::Detach

Microsoft Specific

Interface* Detach( ) throw( );

Remarks

Extracts and returns the encapsulated interface pointer, then clears the encapsulated pointer storage to NULL. This removes the interface pointer from encapsulation. It is up to you to call Release on the returned interface pointer.

_com_ptr_t Overview

END Microsoft Specific


_com_ptr_t::GetActiveObject

Microsoft Specific

HRESULT GetActiveObject( const CLSID& rclsid ) throw( );

HRESULT GetActiveObject( LPOLESTR clsidString ) throw( );

HRESULT GetActiveObject( LPCSTR clsidStringA ) throw( );

Parameters

rclsid

the CLSID of an object

clsidString

a Unicode string that holds either a CLSID (starting with “{“) or a ProgID

clsidStringA

a multibyte string that holds either a CLSID (starting with “{“) or a ProgID

Remarks

Attaches to an existing instance of an object given a CLSID or ProgID. These member functions call GetActiveObject to retrieve a pointer to a running object that has been registered with OLE and then queries for this smart pointer’s interface type. The resulting pointer is then encapsulated within this _com_ptr_t object. Release is called to decrement the reference count for the previously encapsulated pointer. This routine returns the HRESULT to indicate success or failure.

  • GetActiveObject( rclsid ) Attaches to an existing instance of an object given a CLSID.

  • GetActiveObject( clsidString ) Attaches to an existing instance of an object given a Unicode string which holds either a CLSID (starting with “{“) or a ProgID.

  • GetActiveObject( clsidStringA ) Attaches to an existing instance of an object given a multibyte character string which holds either a CLSID (starting with “{“) or a ProgID. Calls MultiByteToWideChar, which assumes that the string is in the ANSI code page rather than an OEM code page.

_com_ptr_t Overview

END Microsoft Specific


_com_ptr_t::GetInterfacePtr

Microsoft Specific

Interface* GetInterfacePtr( ) const throw( );

Remarks

Returns the encapsulated interface pointer, which may be NULL.

_com_ptr_t Overview

END Microsoft Specific


_com_ptr_t::QueryInterface

Microsoft Specific

template<typename _InterfaceType> HRESULT QueryInterface ( const IID& iid, _InterfaceType*& p ) throw ( );

template<typename _InterfaceType> HRESULT QueryInterface ( const IID& iid, _InterfaceType** p) throw( );

Parameters

iid

IID of an interface pointer

p

raw interface pointer

Remarks

Calls IUnknown::QueryInterface on the encapsulated interface pointer with the specified IID, and returns the resulting raw interface pointer in p. This routine returns the HRESULT to indicate success or failure.

_com_ptr_t Overview

END Microsoft Specific


_com_ptr_t::Release

Microsoft Specific

void Release( ) throw( _com_error );

Remarks

Calls IUnknown::Release on the encapsulated interface pointer, raising an E_POINTER error if this interface pointer is NULL.

_com_ptr_t Overview

END Microsoft Specific


_com_ptr_t::operator =

Microsoft Specific

_com_ptr_t& operator=( Interface* pInterface ) throw( );

_com_ptr_t& operator=( int NULL ) throw( _com_error );

template< > _com_ptr_t& operator=( const _com_ptr_t& cp ) throw( );

template< > _com_ptr_t& operator=( const _variant_t& varSrc ) throw( _com_error );

template<typename _InterfacePtr> _com_ptr_t& operator=( const _InterfacePtr& p ) throw( _com_error );

Remarks

Assigns an interface pointer to this _com_ptr_t object:

  • operator=( pInterface ) Encapsulates a raw interface pointer of this smart pointer’s type. AddRef is called to increment the reference count for the encapsulated interface pointer, and Release is called to decrement the reference count for the previously encapsulated pointer.

  • operator=( NULL ) Sets a smart pointer to NULL. The NULL argument must be a zero.

  • operator=( cp ) Sets a smart pointer to be a copy of another instance of the same smart pointer of the same type. AddRef is called to increment the reference count for the encapsulated interface pointer, and Release is called to decrement the reference count for the previously encapsulated pointer.

  • operator=( varSrc ) Sets a smart pointer to be a _variant_t object. The encapsulated VARIANT must be of type VT_DISPATCH or VT_UNKNOWN, or it can be converted to one of these two types. If QueryInterface fails with an E_NOINTERFACE error, a NULL smart pointer results. Any other error causes a _com_error to be raised.

  • operator=( p ) Sets a smart pointer to be a different smart pointer of a different type or a different raw interface pointer. QueryInterface is called to find an interface pointer of this smart pointer’s type, and Release is called to decrement the reference count for the previously encapsulated pointer. If QueryInterface fails with an E_NOINTERFACE, a NULL smart pointer results. Any other error causes a _com_error to be raised.

_com_ptr_t Overview

END Microsoft Specific


_com_ptr_t Relational Operators

Microsoft Specific

template<typename _InterfacePtr> bool operator==( _InterfacePtr p ) throw( _com_error );

template<> bool operator==( Interface* p ) throw( _com_error );

template<> bool operator==( _com_ptr_t& p ) throw( );

template<> bool operator==( int NULL ) throw( _com_error );

template<typename _InterfacePtr> bool operator!=( _InterfacePtr p ) throw( _com_error );

template<> bool operator!=( Interface* p ) throw( _com_error );

template<> bool operator!=( _com_ptr_t& p ) throw( _com_error );

template<> bool operator!=( int NULL ) throw( _com_error );

template<typename _InterfacePtr> bool operator<( _InterfacePtr p ) throw( _com_error );

template<typename _InterfacePtr> bool operator>( _InterfacePtr p ) throw( _com_error );

template<typename _InterfacePtr> bool operator<=( _InterfacePtr p ) throw( _com_error );

template<typename _InterfacePtr> bool operator>=( _InterfacePtr p ) throw( _com_error );

Remarks

Compares a smart pointer object to another smart pointer, raw interface pointer, or NULL. Except for the NULL pointer tests, these operators first query both pointers for IUnknown, and compare the results.

_com_ptr_t Overview

END Microsoft Specific


_com_ptr_t Extractors

Microsoft Specific

operator Interface*( ) const throw( );

operator Interface&( ) const throw( _com_error );

Interface& operator*( ) const throw( _com_error );

Interface* operator->( ) const throw( _com_error );

Interface** operator&( ) throw( );

operator bool( ) const throw( );

Remarks

  • operator Interface* Returns the encapsulated interface pointer, which may be NULL.

  • operator Interface& Returns a reference to the encapsulated interface pointer, and issues an error if the pointer is NULL.

  • operator* Allows a smart pointer object to act as though it were the actual encapsulated interface when dereferenced.

  • operator-> Allows a smart pointer object to act as though it were the actual encapsulated interface when dereferenced.

  • operator& Releases any encapsulated interface pointer, replacing it with NULL, and returns the address of the encapsulated pointer. This allows the smart pointer to be passed by address to a function which has an out parameter through which it returns an interface pointer.

  • operator bool Allows a smart pointer object to be used in a conditional expression. This operator returns true if the pointer is not NULL.

_com_ptr_t Overview

END Microsoft Specific


Relational Function Templates

Microsoft Specific

template<typename _InterfaceType> bool operator==( int NULL, _com_ptr_t<_InterfaceType>& p ) throw( _com_error );

template<typename _Interface, typename _InterfacePtr> bool operator==( _Interface* i, _com_ptr_t<_InterfacePtr>& p ) throw( _com_error );

template<typename _Interface> bool operator!=( int NULL, _com_ptr_t<_Interface>& p ) throw( _com_error );

template<typename _Interface, typename _InterfacePtr> bool operator!=( _Interface* i, _com_ptr_t<_InterfacePtr>& p ) throw( _com_error );

template<typename _Interface> bool operator<( int NULL, _com_ptr_t<_Interface>& p ) throw( _com_error );

template<typename _Interface, typename _InterfacePtr> bool operator<( _Interface* i, _com_ptr_t<_InterfacePtr>& p ) throw( _com_error );

template<typename _Interface> bool operator>( int NULL, _com_ptr_t<_Interface>& p ) throw( _com_error );

template<typename _Interface, typename _InterfacePtr> bool operator>( _Interface* i, _com_ptr_t<_InterfacePtr>& p ) throw( _com_error );

template<typename _Interface> bool operator<=( int NULL, _com_ptr_t<_Interface>& p ) throw( _com_error );

template<typename _Interface, typename _InterfacePtr> bool operator<=( _Interface* i, _com_ptr_t<_InterfacePtr>& p ) throw( _com_error );

template<typename _Interface> bool operator>=( int NULL, _com_ptr_t<_Interface>& p ) throw( _com_error );

template<typename _Interface, typename _InterfacePtr> bool operator>=( _Interface* i, _com_ptr_t<_InterfacePtr>& p ) throw( _com_error );

Parameters

i

a raw interface pointer

p

a smart pointer

Remarks

They are function templates which allow comparison with a smart pointer on the right-hand side of the comparison operator. These are not member functions of _com_ptr_t.

_com_ptr_t Overview

END Microsoft Specific


_bstr_t

Microsoft Specific

A _bstr_t object encapsulates the BSTR data type. The class manages resource allocation and deallocation, via function calls to SysAllocString and SysFreeString, and other BSTR APIs when appropriate. The _bstr_t class uses reference counting to avoid excessive overhead.

#include <comdef.h>

Compiler COM Support Class Overview

Construction

_bstr_t Constructs a _bstr_t object.

Operations

copy | Constructs a copy of the encapsulated BSTR.
length | Returns the length of the encapsulated BSTR.

Operators

operator = | Assigns a new value to an existing _bstr_t object.
operator += | Appends characters to the end of the _bstr_t object.
operator + | Concatenates two strings.
operator ! | Checks if the encapsulated BSTR is a NULL string.
operator ==, !=, <, >, <=, >= | Compares two _bstr_t objects.
operator wchar_t*, char* | Extract the pointers to the encapsulated Unicode or multibyte BSTR object.

END Microsoft Specific


_bstr_t::_bstr_t

Microsoft Specific

_bstr_t( ) throw( );

_bstr_t( const _bstr_t& s1 ) throw( );

_bstr_t( const char* s2 ) throw( _com_error );

_bstr_t( const wchar_t* s3 ) throw( _com_error );

_bstr_t( const _variant_t& var ) throw ( _com_error );

_bstr_t( BSTR bstr, bool fCopy ) throw ( _com_error );

Parameters

s1

a _bstr_t object to be copied

s2

a multibyte string

s3

a Unicode string

var

a _variant_t object

bstr

an existing BSTR object

fCopy

if false, the bstr argument is attached to the new object without making a copy by calling SysAllocString.

Remarks

Constructs a _bstr_t object.

  • _bstr_t( ) Constructs a default _bstr_t object that encapsulates a NULL BSTR object.

  • _bstr_t( _bstr_t& s1 ) Constructs a _bstr_t object as a copy of another. This is a “shallow” copy, which increments the reference count of the encapsulated BSTR object instead of creating a new one.

  • _bstr_t( char* s2 ) Constructs a _bstr_t object by calling SysAllocString to create a new BSTR object and encapsulate it. This constructor first performs a multibyte to Unicode conversion.

  • _bstr_t( wchar_t* s3 ) Constructs a _bstr_t object by calling SysAllocString to create a new BSTR object and encapsulates it.

  • _bstr_t( _variant_t& var ) Constructs a _bstr_t object from a _variant_t object by first retrieving a BSTR object from the encapsulated VARIANT object.

  • _bstr_t( BSTR bstr, bool fCopy ) Constructs a _bstr_t object from an existing BSTR (as opposed to a wchar_t* string). If fCopy is false, the supplied BSTR is attached to the new object without making a new copy via SysAllocString. This is the method used by the wrapper functions in the type library headers to encapsulate and take ownership of a BSTR, returned by an interface method, in a _bstr_t object.

_bstr_t Overview

END Microsoft Specific


_bstr_t::copy

Microsoft Specific

BSTR copy( ) const throw(_com_error);

Remarks

Returns a newly allocated copy of the encapsulated BSTR object.

_bstr_t Overview

END Microsoft Specific


_bstr_t::length

Microsoft Specific

unsigned int length ( ) const throw( );

Remarks

Returns the length of the encapsulated BSTR object.

_bstr_t Overview

END Microsoft Specific


_bstr_t::operator =

Microsoft Specific

_bstr_t& operator=( const _bstr_t& s1 ) throw ( );

_bstr_t& operator=( const char* s2 ) throw( _com_error );

_bstr_t& operator=( const wchar_t* s3 ) throw( _com_error );

_bstr_t& operator=( const _variant_t& var ) throw( _com_error );

Parameters

s1

a _bstr_t object to be assigned to an existing _bstr_t object

s2

a multibyte string to be assigned to an existing _bstr_t object

s3

a Unicode string to be assigned to an existing _bstr_t object

var

a _variant_t object to be assigned to an existing _bstr_t object

Remarks

Assigns a new value to an existing _bstr_t object.

_bstr_t Overview

END Microsoft Specific


_bstr_t::operator +=, +

Microsoft Specific

_bstr_t& operator+=( const _bstr_t& s1 ) throw( _com_error );

_bstr_t operator+( const _bstr_t& s1 ) const throw( _com_error );

friend _bstr_t operator+( const char* s2, const _bstr_t& s1 );

friend _bstr_t operator+( const wchar_t* s3, const _bstr_t& s1 );

Parameters

s1

a _bstr_t object

s2

a multibyte string

s3

a Unicode string

Remarks

These operators perform string concatenation:

  • operator+=( s1 ) Appends the characters in the encapsulated BSTR of s1 to the end of this object’s encapsulated BSTR.

  • operator+( s1 ) Returns the new _bstr_t which is formed by concatenating this object’s BSTR with that of s1.

  • operator+( s2, s1 ) Returns a new _bstr_t which is formed by concatenating a multibyte string s2, converted to Unicode, with the BSTR encapsulated in s1.

  • operator+( s3, s1 ) Returns a new _bstr_t which is formed by concatenating a Unicode string s3 with the BSTR encapsulated in s1.

_bstr_t Overview

END Microsoft Specific


_bstr_t::operator !

Microsoft Specific

bool operator!( ) const throw( );

Remarks

Checks if the encapsulated BSTR object is the NULL string. It returns true if yes, false if not.

_bstr_t Overview

END Microsoft Specific


_bstr_t Relational Operators

Microsoft Specific

bool operator==( const _bstr_t& str ) const throw( );

bool operator!=( const _bstr_t& str ) const throw( );

bool operator<( const _bstr_t& str ) const throw( );

bool operator>( const _bstr_t& str ) const throw( );

bool operator<=( const _bstr_t& str ) const throw( );

bool operator>=( const _bstr_t& str ) const throw( );

Remarks

These operators compare two _bstr_t objects lexicographically. The operators return true if the comparisons hold, otherwise return false.

_bstr_t Overview

END Microsoft Specific


_bstr_t::wchar_t*, _bstr_t::char*

Microsoft Specific

operator const wchar_t*( ) const throw( );

operator wchar_t*( ) const throw( );

operator const char*( ) const throw( _com_error );

operator char*( ) const throw( _com_error );

Remarks

These operators can be used to extract raw pointers to the encapsulated Unicode or multibyte BSTR object. The operators return the pointer to the actual internal buffer, so the resulting string cannot be modified.

_bstr_t Overview

END Microsoft Specific


_variant_t

Microsoft Specific

A _variant_t object encapsulates the VARIANT data type. The class manages resource allocation and deallocation, and makes function calls to VariantInit and VariantClear as appropriate.

#include <comdef.h>

Compiler COM Support Class Overview

Construction

_variant_t Constructs a _variant_t object.

Operations

Attach | Attaches a VARIANT object into the _variant_t object.
Clear | Clears the encapsulated VARIANT object.
ChangeType | Changes the type of the _variant_t object to the indicated VARTYPE.
Detach | Detaches the encapsulated VARIANT object from this _variant_t object.
SetString | Assigns a string to this _variant_t object.

Operators

operator = | Assigns a new value to an existing _variant_t object.
operator ==, != | Compare two _variant_t objects for equality or inequality.
Extractors | Extract data from the encapsulated VARIANT object.

END Microsoft Specific


_variant_t::_variant_t

Microsoft Specific

_variant_t( ) throw( );

_variant_t( const VARIANT& varSrc ) throw( _com_error );

_variant_t( const VARIANT* pVarSrc ) throw( _com_error );

_variant_t( const _variant_t& var_t_Src ) throw( _com_error );

_variant_t( VARIANT& varSrc, bool fCopy ) throw( _com_error );

_variant_t( short sSrc, VARTYPE vtSrc = VT_I2 ) throw( _com_error );

_variant_t( long lSrc, VARTYPE vtSrc = VT_I4 ) throw( _com_error );

_variant_t( float fltSrc ) throw( );

_variant_t( double dblSrc, VARTYPE vtSrc = VT_R8 ) throw( _com_error );

_variant_t( const CY& cySrc ) throw( );

_variant_t( const _bstr_t& bstrSrc ) throw( _com_error );

_variant_t( const wchar_t *wstrSrc ) throw( _com_error );

_variant_t( const char* strSrc ) throw( _com_error );

_variant_t( bool bSrc ) throw( );

_variant_t( IUnknown* pIUknownSrc, bool fAddRef = true ) throw( );

_variant_t( IDispatch* pDispSrc, bool fAddRef = true ) throw( );

_variant_t( const DECIMAL& decSrc ) throw( );

_variant_t( BYTE bSrc ) throw( );

Parameters

varSrc

a VARIANT object to be copied into the new _variant_t object

pVarSrc

pointer to a VARIANT object to be copied into the new _variant_t object

var_t_Src

a _variant_t object to be copied into the new _variant_t object

fCopy

if false, the supplied VARIANT object is attached to the new _variant_t object without making a new copy by VariantCopy

ISrc, sSrc

an integer value to be copied into the new _variant_t object

vtSrc

the VARTYPE for the new _variant_t object

fltSrc, dblSrc

a numerical value to be copied into the new _variant_t object

cySrc

a CY object to be copied into the new _variant_t object

bstrSrc

a _bstr_t object to be copied into the new _variant_t object

strSrc, wstrSrc

a string to be copied into the new _variant_t object

bSrc

a bool value to be copied into the new _variant_t object

pIUknownSrc

COM interface pointer to a VT_UNKNOWN object to be encapsulated into the new _variant_t object

pDispSrc

COM interface pointer to a VT_DISPATCH object to be encapsulated into the new _variant_t object

decSrc

a DECIMAL value to be copied into the new _variant_t object

bSrc

a BYTE value to be copied into the new _variant_t object

Remarks

Constructs a _variant_t object.

  • _variant_t( ) Constructs an empty _variant_t object, VT_EMPTY.

  • _variant_t( VARIANT& varSrc ) Constructs a _variant_t object from a copy of the VARIANT object. The variant type is retained.

  • _variant_t( VARIANT* pVarSrc ) Constructs a _variant_t object from a copy of the VARIANT object. The variant type is retained.

  • _variant_t( _variant_t& var_t_Src ) Constructs a _variant_t object from another _variant_t object. The variant type is retained.

  • _variant_t( VARIANT& varSrc, bool fCopy ) Constructs a _variant_t object from an existing VARIANT object. If fCopy is false, the VARIANT object is attached to the new object without making a copy.

  • _variant_t( short sSrc, VARTYPE vtSrc = VT_I2 ) Constructs a _variant_t object of type VT_I2 or VT_BOOL from a short integer value. Any other VARTYPE results in an E_INVALIDARG error.

  • _variant_t( long lSrc, VARTYPE vtSrc = VT_I4 ) Constructs a _variant_t object of type VT_I4, VT_BOOL, or VT_ERROR from a long integer value. Any other VARTYPE results in an E_INVALIDARG error.

  • _variant_t( float fltSrc ) Constructs a _variant_t object of type VT_R4 from a float numerical value.

  • _variant_t( double dblSrc, VARTYPE vtSrc = VT_R8 ) Constructs a _variant_t object of type VT_R8 or VT_DATE from a double numerical value. Any other VARTYPE results in an E_INVALIDARG error.

  • _variant_t( CY& cySrc ) Constructs a _variant_t object of type VT_CY from a CY object.

  • _variant_t( _bstr_t& bstrSrc ) Constructs a _variant_t object of type VT_BSTR from a _bstr_t object. A new BSTR is allocated.

  • _variant_t( wchar_t *wstrSrc ) Constructs a _variant_t object of type VT_BSTR from a Unicode string. A new BSTR is allocated.

  • _variant_t( char* strSrc ) Constructs a _variant_t object of type VT_BSTR from a string. A new BSTR is allocated.

  • _variant_t( bool bSrc ) Constructs a _variant_t object of type VT_BOOL from a bool value.

  • _variant_t( IUnknown* pIUknownSrc, bool fAddRef = true ) Constructs a _variant_t object of type VT_UNKNOWN from a COM interface pointer. If fAddRef is true, then AddRef is called on the supplied interface pointer to match the call to Release that will occur when the _variant_t object is destroyed. It is up to you to call Release on the supplied interface pointer. If fAddRef is false, this constructor takes ownership of the supplied interface pointer; do not call Release on the supplied interface pointer.

  • _variant_t( IDispatch* pDispSrc, bool fAddRef = true ) Constructs a _variant_t object of type VT_DISPATCH from a COM interface pointer. If fAddRef is true, then AddRef is called on the supplied interface pointer to match the call to Release that will occur when the _variant_t object is destroyed. It is up to you to call Release on the supplied interface pointer. If fAddRef is false, this constructor takes ownership of the supplied interface pointer; do not call Release on the supplied interface pointer.

  • _variant_t( DECIMAL& decSrc ) Constructs a _variant_t object of type VT_DECIMAL from a DECIMAL value.

  • _variant_t( BYTE bSrc ) Constructs a _variant_t object of type VT_UI1 from a BYTE value.

_variant_t Overview

END Microsoft Specific


_variant_t::Attach

Microsoft Specific

void Attach( VARIANT& varSrc ) throw( _com_error );

Parameters

varSrc

a VARIANT object to be attached to this _variant_t object

Remarks

Takes ownership of the VARIANT by encapsulating it. This member function releases any existing encapsulated VARIANT, then copies the supplied VARIANT, and sets its VARTYPE to VT_EMPTY to make sure its resources can only be released by the _variant_t destructor.

_variant_t Overview

END Microsoft Specific


_variant_t::Clear

Microsoft Specific

void Clear( ) throw( _com_error );

Remarks

Calls VariantClear on the encapsulated VARIANT object.

_variant_t Overview

END Microsoft Specific


_variant_t::ChangeType

void ChangeType( VARTYPE vartype, const _variant_t* pSrc = NULL ) throw( _com_error );

Parameters

vartype

the VARTYPE for this _variant_t object

pSrc

a pointer to the _variant_t object to be converted. If this value is NULL, conversion is done in place.

Remarks

This member function converts a _variant_t object into the indicated VARTYPE. If pSrc is NULL, the conversion is done in place, otherwise this _variant_t object is copied from pSrc and then converted.

_variant_t Overview

END Microsoft Specific


_variant_t::Detach

Microsoft Specific

VARIANT Detach( ) throw( _com_error );

Return Value

The encapsulated VARIANT.

Remarks

Extracts and returns the encapsulated VARIANT, then clears this _variant_t object without destroying it. This member function removes the VARIANT from encapsulation and sets the VARTYPE of this _variant_t object to VT_EMPTY. It is up to you to release the returned VARIANT by calling the VariantInit function.

_variant_t Overview

END Microsoft Specific


_variant_t::SetString

Microsoft Specific

void SetString( const char* pSrc ) throw( _com_error );

Parameter

pSrc

pointer to the character string

Remarks

Converts an ANSI character string to a Unicode BSTR string and assigns it to this _variant_t object.

_variant_t Overview

END Microsoft Specific


_variant_t::operator =

Microsoft Specific

_variant_t& operator=( const VARIANT& varSrc ) throw( _com_error );

_variant_t& operator=( const VARIANT* pVarSrc ) throw( _com_error );

_variant_t& operator=( const _variant_t& var_t_Src ) throw( _com_error );

_variant_t& operator=( short sSrc ) throw( _com_error );

_variant_t& operator=( long lSrc ) throw( _com_error );

_variant_t& operator=( float fltSrc ) throw( _com_error );

_variant_t& operator=( double dblSrc ) throw( _com_error );

_variant_t& operator=( const CY& cySrc ) throw( _com_error );

_variant_t& operator=( const _bstr_t& bstrSrc ) throw( _com_error );

_variant_t& operator=( const wchar_t* wstrSrc ) throw( _com_error );

_variant_t& operator=( const char* strSrc ) throw( _com_error );

_variant_t& operator=( IDispatch* pDispSrc ) throw( _com_error );

_variant_t& operator=( bool bSrc ) throw( _com_error );

_variant_t& operator=( IUnknown* pSrc ) throw( _com_error );

_variant_t& operator=( const DECIMAL& decSrc ) throw( _com_error );

_variant_t& operator=( BYTE bSrc ) throw( _com_error );

Remarks

The operator assigns a new value to the _variant_t object:

  • operator=( varSrc ) Assigns an existing VARIANT to a _variant_t object.

  • operator=( pVarSrc ) Assigns an existing VARIANT to a _variant_t object.

  • operator=( var_t_Src ) Assigns an existing _variant_t object to a _variant_t object.

  • operator=( sSrc ) Assigns a short integer value to a _variant_t object.

  • operator=( lSrc ) Assigns a long integer value to a _variant_t object.

  • operator=( fltSrc ) Assigns a float numerical value to a _variant_t object.

  • operator=( dblSrc ) Assigns a double numerical value to a _variant_t object.

  • operator=( cySrc ) Assigns a CY object to a _variant_t object.

  • operator=( bstrSrc ) Assigns a BSTR object to a _variant_t object.

  • operator=( wstrSrc ) Assigns a Unicode string to a _variant_t object.

  • operator=( strSrc ) Assigns a multibyte string to a _variant_t object.

  • operator=( bSrc ) Assigns a bool value to a _variant_t object.

  • operator=( pDispSrc ) Assigns a VT_DISPATCH object to a _variant_t object.

  • operator=( pIUnknownSrc ) Assigns a VT_UNKNOWN object to a _variant_t object.

  • operator=( decSrc ) Assigns a DECIMAL value to a _variant_t object.

  • operator=( bSrc ) Assigns a BYTE value to a _variant_t object.

_variant_t Overview

END Microsoft Specific


_variant_t Relational Operators

Microsoft Specific

bool operator==( const VARIANT& varSrc ) const throw( _com_error );

bool operator==( const VARIANT* pSrc ) const throw( _com_error );

bool operator!=( const VARIANT& varSrc ) const throw( _com_error );

bool operator!=( const VARIANT* pSrc ) const throw( _com_error );

Parameter

varSrc

a VARIANT to be compared with the _variant_t object

pSrc

pointer to the VARIANT to be compared with the _variant_t object

Remarks

Compares a _variant_t object with a VARIANT, testing for equality or inequality. Returns true if comparison holds, false if not.

_variant_t Overview

END Microsoft Specific


_variant_t Extractors

Microsoft Specific

operator short( ) const throw( _com_error );

operator long( ) const throw( _com_error);

operator float( ) const throw( _com_error );

operator double( ) const throw( _com_error );

operator CY( ) const throw( _com_error );

operator bool( ) const throw( _com_error );

operator DECIMAL( ) const throw( _com_error );

operator BYTE( ) const throw( _com_error );

operator _bstr_t( ) const throw( _com_error );

operator IDispatch*( ) const throw( _com_error );

operator IUnknown*( ) const throw( _com_error );

Remarks

Extracts raw data from an encapsulated VARIANT. If the VARIANT is not already the proper type, VariantChangeType is used to attempt a conversion, and an error is generated upon failure:

  • operator short( ) Extracts a short integer value.

  • operator long( ) Extracts a long integer value.

  • operator float( ) Extracts a float numerical value.

  • operator double( ) Extracts a double integer value.

  • operator CY( ) Extracts a CY object.

  • operator bool( ) Extracts a bool value.

  • operator DECIMAL( ) Extracts a DECIMAL value.

  • operator BYTE( ) Extracts a BYTE value.

  • operator _bstr_t( ) Extracts a string, which is encapsulated in a _bstr_t object.

  • operator IDispatch*( ) Extracts a dispinterface pointer from an encapsulated VARIANT. AddRef is called on the resulting pointer, so it is up to you to call Release to free it.

  • operator IUnknown*( ) Extracts a COM interface pointer from an encapsulated VARIANT. AddRef is called on the resulting pointer, so it is up to you to call Release to free it.

_variant_t Overview

END Microsoft Specific


Charts

This appendix contains the following charts:

  • ASCII Character Codes

  • ASCII Multilingual Codes

  • ANSI Character Codes

  • Key Codes


ASCII Character Codes

The ASCII character code tables contain the decimal and hexadecimal values of the extended ASCII (American Standards Committee for Information Interchange) character set. The extended character set includes the ASCII character set and 128 other characters for graphics and line drawing, often called the “IBM® character set.”

  • Chart 1 (codes 0–127)

  • Chart 2 (codes 128–255)


ASCII Character Codes Chart 1


ASCII Character Codes Chart 2


ASCII Multilingual Codes

There are a number of variants on the IBM character set, called “code pages.” Systems sold in some European countries use the multilingual character set known as Code Page 850, which contains fewer graphics symbols and more accented letters and special characters.


ASCII Multilingual Codes Chart


ANSI Character Codes

The ANSI character code chart lists the extended character set of most of the programs used by Windows. The codes of the ANSI (American National Standards Institute) character set from 32 through 126 are displayable characters from the ASCII character set. The ANSI characters displayed as solid blocks are undefined characters and may appear differently on output devices.


ANSI Character Codes Chart


Key Codes

Some keys, such as function keys, cursor keys, and ALT+KEY combinations, have no ASCII code. When a key is pressed, a microprocessor within the keyboard generates an “extended scan code” of two bytes. The first (low-order) byte contains the ASCII code, if any. The second (high-order) byte has the scan code—a unique code generated by the keyboard when a key is either pressed or released. Because the extended scan code is more extensive than the standard ASCII code, programs can use it to identify keys which do not have an ASCII code.


Key Codes Chart 1


Key Codes Chart 2


C Language Reference

The C language is a general-purpose programming language known for its efficiency, economy, and portability. While these characteristics make it a good choice for almost any kind of programming, C has proven especially useful in systems programming because it facilitates writing fast, compact programs that are readily adaptable to other systems. Well-written C programs are often as fast as assembly-language programs, and they are typically easier for programmers to read and maintain.

Organization of C Language Reference
Interesting home pages
Visual C++ Home The entire Visual C++ product.


Organization of the C Language Reference

  • Elements of C

  • Program Structure

  • Declarations and Types

  • Expressions and Assignments

  • Statements

  • Functions

  • C Language Syntax Summary

  • Implementation-Defined Behavior


Scope of this Manual

C is a flexible language that leaves many programming decisions up to you. In keeping with this philosophy, C imposes few restrictions in matters such as type conversion. Although this characteristic of the language can make your programming job easier, you must know the language well to understand how programs will behave. This book provides information on the C language components and the features of the Microsoft implementation. The syntax for the C language is from ANSI X3.159-1989, American National Standard for Information Systems – Programming Language – C (hereinafter called the ANSI C standard), although it is not part of the ANSI C standard. Appendix A, C Language Syntax Summary, provides the syntax and a description of how to read and use the syntax definitions.

This book does not discuss programming with C++. See C++ Language Reference for information about the C++ language.

Note For information on Microsoft product support, see the Pss.hlp file.


ANSI Conformance

Microsoft® C conforms to the standard for the C language as set forth in the ANSI C standard. Microsoft extensions to the ANSI C standard are noted in the text and syntax of this book as well as in the online reference. Because the extensions are not a part of the ANSI C standard, their use may restrict portability of programs between systems. By default, the Microsoft extensions are enabled. To disable the extensions, specify the /Za compiler option. With /Za, all non-ANSI code generates errors or warnings.


Elements of C

This chapter describes the elements of the C programming language, including the names, numbers, and characters used to construct a C program. The ANSI C syntax labels these components “tokens.” This chapter explains how to define tokens and how the compiler evaluates them.

The following topics are discussed:

  • Tokens

  • Comments

  • Keywords

  • Identifiers

  • Constants

  • String literals

  • Punctuation and special characters

The chapter also includes reference tables for trigraphs, floating-point constants, integer constants, and escape sequences.

“Operators” are symbols (both single characters and character combinations) that specify how values are to be manipulated. Each symbol is interpreted as a single unit, called a token. For more information, see Operators in Chapter 4.


C Tokens

In a C source program, the basic element recognized by the compiler is the “token.” A token is source-program text that the compiler does not break down into component elements.

Syntax

token :

keyword
identifier
constant
string-literal
operator
punctuator

Note See the introduction to Appendix A, C Language Syntax Summary, for an explanation of the ANSI syntax conventions.

The keywords, identifiers, constants, string literals, and operators described in this chapter are examples of tokens. Punctuation characters such as brackets ([ ]), braces ({ }), parentheses ( ( ) ), and commas (,) are also tokens.


White-Space Characters

Space, tab, linefeed, carriage-return, formfeed, vertical-tab, and newline characters are called “white-space characters” because they serve the same purpose as the spaces between words and lines on a printed page—they make reading easier. Tokens are delimited (bounded) by white-space characters and by other tokens, such as operators and punctuation. When parsing code, the C compiler ignores white-space characters unless you use them as separators or as components of character constants or string literals. Use white-space characters to make a program more readable. Note that the compiler also treats comments as white space.


C Comments

A “comment” is a sequence of characters beginning with a forward slash/asterisk combination (/*) that is treated as a single white-space character by the compiler and is otherwise ignored. A comment can include any combination of characters from the representable character set, including newline characters, but excluding the “end comment” delimiter (*/). Comments can occupy more than one line but cannot be nested.

Comments can appear anywhere a white-space character is allowed. Since the compiler treats a comment as a single white-space character, you cannot include comments within tokens. The compiler ignores the characters in the comment.

Use comments to document your code. This example is a comment accepted by the compiler:

/* Comments can contain keywords such as
   for and while without generating errors. */

Comments can appear on the same line as a code statement:

printf( "Hello\n" );  /* Comments can go here */

You can choose to precede functions or program modules with a descriptive comment block:

/* MATHERR.C illustrates writing an error routine
 * for math functions.
 */

Since comments cannot contain nested comments, this example causes an error:

/* Comment out this routine for testing

   /* Open file */
    fh = _open( "myfile.c", _O_RDONLY );
    .
    .
    .
 */

The error occurs because the compiler recognizes the first */, after the words Open file, as the end of the comment. It tries to process the remaining text and produces an error when it finds the */ outside a comment.

While you can use comments to render certain lines of code inactive for test purposes, the preprocessor directives #if and #endif and conditional compilation are a useful alternative for this task. For more information, see Preprocessor Directives in the Preprocessor Reference.

Microsoft Specific —>

The Microsoft compiler also supports single-line comments preceded by two forward slashes (//). If you compile with /Za (ANSI standard), these comments generate errors. These comments cannot extend to a second line.

// This is a valid comment

Comments beginning with two forward slashes (//) are terminated by the next newline character that is not preceded by an escape character. In the next example, the newline character is preceded by a backslash (\), creating an “escape sequence.” This escape sequence causes the compiler to treat the next line as part of the previous line. (For more information, see Escape Sequences.)

// my comment \
    i++;

Therefore, the i++; statement is commented out.

The default for Microsoft C is that the Microsoft extensions are enabled. Use /Za to disable these extensions.

END Microsoft Specific


Evaluation of Tokens

When the compiler interprets tokens, it includes as many characters as possible in a single token before moving on to the next token. Because of this behavior, the compiler may not interpret tokens as you intended if they are not properly separated by white space. Consider the following expression:

i+++j

In this example, the compiler first makes the longest possible operator (++) from the three plus signs, then processes the remaining plus sign as an addition operator (+). Thus, the expression is interpreted as (i++) + (j), not (i) + (++j). In this and similar cases, use white space and parentheses to avoid ambiguity and ensure proper expression evaluation.

Microsoft Specific —>

The C compiler treats a CTRL+Z character as an end-of-file indicator. It ignores any text after CTRL+Z.

END Microsoft Specific


C Keywords

“Keywords” are words that have special meaning to the C compiler. In translation phases 7 and 8, an identifier cannot have the same spelling and case as a C keyword. (See a description of translation phases in the Preprocessor Reference; for information on identifiers, see Identifiers.) The C language uses the following keywords:

auto | double | int | struct
break | else | long | switch
case | enum | register | typedef
char | extern | return | union
const | float | short | unsigned
continue | for | signed | void
default | goto | sizeof | volatile
do | if | static | while

You cannot redefine keywords. However, you can specify text to be substituted for keywords before compilation by using C preprocessor directives.

Microsoft Specific —>

The ANSI C standard allows identifiers with two leading underscores to be reserved for compiler implementations. Therefore, the Microsoft convention is to precede Microsoft-specific keyword names with double underscores. These words cannot be used as identifier names. For a description of the ANSI rules for naming identifiers, including the use of double underscores, see Identifiers.

The following keywords and special identifiers are recognized by the Microsoft C compiler:

__asm | dllimport2 | __int8 | naked2
__based1 | __except | __int16 | __stdcall
__cdecl | __fastcall | __int32 | thread2
__declspec | __finally | __int64 | __try
dllexport2 | __inline | __leave |

1. The __based keyword has limited uses for 32-bit target compilations.

2. These are special identifiers when used with __declspec; their use in other contexts is not restricted.

Microsoft extensions are enabled by default. To ensure that your programs are fully portable, you can disable Microsoft extensions by specifying the /Za option (compile for ANSI compatibility) during compilation. When you do this, Microsoft-specific keywords are disabled.

When Microsoft extensions are enabled, you can use the keywords listed above in your programs. For ANSI compliance, most of these keywords are prefaced by a double underscore. The four exceptions, dllexport, dllimport, naked, and thread, are used only with __declspec and therefore do not require a leading double underscore. For backward compatibility, single-underscore versions of the rest of the keywords are supported.

END Microsoft Specific


C Identifiers

“Identifiers” or “symbols” are the names you supply for variables, types, functions, and labels in your program. Identifier names must differ in spelling and case from any keywords. You cannot use keywords (either C or Microsoft) as identifiers; they are reserved for special use. You create an identifier by specifying it in the declaration of a variable, type, or function. In this example, result is an identifier for an integer variable, and main and printf are identifier names for functions.

void main()
{
    int result;

    if ( result != 0 )
      printf( "Bad file handle\n" );
}

Once declared, you can use the identifier in later program statements to refer to the associated value.

A special kind of identifier, called a statement label, can be used in goto statements. (Declarations are described in Chapter 3, Declarations and Types. Statement labels are described in The goto and Labeled Statements in Chapter 5.)

Syntax

identifier :

nondigit
identifier nondigit
identifier digit

nondigit : one of

_ a b c d e f g h i j k l m n o p q r s t u v w x y z
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z

digit : one of

0 1 2 3 4 5 6 7 8 9

The first character of an identifier name must be a nondigit (that is, the first character must be an underscore or an uppercase or lowercase letter). ANSI allows six significant characters in an external identifier’s name and 31 for names of internal (within a function) identifiers. External identifiers (ones declared at global scope or declared with storage class extern) may be subject to additional naming restrictions because these identifiers have to be processed by other software such as linkers.

Microsoft Specific —>

Although ANSI allows 6 significant characters in external identifier names and 31 for names of internal (within a function) identifiers, the Microsoft C compiler allows 247 characters in an internal or external identifier name. If you aren’t concerned with ANSI compatibility, you can modify this default to a smaller or larger number using the /H (restrict length of external names) option.

END Microsoft Specific

The C compiler considers uppercase and lowercase letters to be distinct characters. This feature, called “case sensitivity,” enables you to create distinct identifiers that have the same spelling but different cases for one or more of the letters. For example, each of the following identifiers is unique:

add
ADD
Add
aDD

Microsoft Specific —>

Do not select names for identifiers that begin with two underscores or with an underscore followed by an uppercase letter. The ANSI C standard allows identifier names that begin with these character combinations to be reserved for compiler use. Identifiers with file-level scope should also not be named with an underscore and a lowercase letter as the first two letters. Identifier names that begin with these characters are also reserved. By convention, Microsoft uses an underscore and an uppercase letter to begin macro names and double underscores for Microsoft-specific keyword names. To avoid any naming conflicts, always select identifier names that do not begin with one or two underscores, or names that begin with an underscore followed by an uppercase letter.

END Microsoft Specific

The following are examples of valid identifiers that conform to either ANSI or Microsoft naming restrictions:

j
count
temp1
top_of_page
skip12
LastNum

Microsoft Specific —>

Although identifiers in source files are case sensitive by default, symbols in object files are not. Microsoft C treats identifiers within a compilation unit as case sensitive.

The Microsoft linker is case sensitive. You must specify all identifiers consistently according to case.

The “source character set” is the set of legal characters that can appear in source files. For Microsoft C, the source set is the standard ASCII character set. The source character set and execution character set include the ASCII characters used as escape sequences. See Character Constants for information about the execution character set.

END Microsoft Specific

An identifier has “scope,” which is the region of the program in which it is known, and “linkage,” which determines whether the same name in another scope refers to the same identifier. These topics are explained in Lifetime, Scope, Visibility, and Linkage in Chapter 2.


Multibyte and Wide Characters

A multibyte character is a character composed of sequences of one or more bytes. Each byte sequence represents a single character in the extended character set. Multibyte characters are used in character sets such as Kanji.

Wide characters are multilingual character codes that are always 16 bits wide. The type for character constants is char; for wide characters, the type is wchar_t. Since wide characters are always a fixed size, using wide characters simplifies programming with international character sets.

The wide-character-string literal L"hello" becomes an array of six integers of type wchar_t.

{L'h', L'e', L'l', L'l', L'o', 0}

The Unicode specification is the specification for wide characters. The run-time library routines for translating between multibyte and wide characters include mbstowcs, mbtowc, wcstombs, and wctomb.


Trigraphs

The source character set of C source programs is contained within the 7-bit ASCII character set but is a superset of the ISO 646-1983 Invariant Code Set. Trigraph sequences allow C programs to be written using only the ISO (International Standards Organization) Invariant Code Set. Trigraphs are sequences of three characters (introduced by two consecutive question marks) that the compiler replaces with their corresponding punctuation characters. You can use trigraphs in C source files with a character set that does not contain convenient graphic representations for some punctuation characters.

Table 1.1 shows the nine trigraph sequences. All occurrences in a source file of the punctuation characters in the first column are replaced with the corresponding character in the second column.

Table 1.1 Trigraph Sequences

Trigraph | Punctuation Character
??= | #
??( | [
??/ | \
??) | ]
??’ | ^
??< | {
??! | |
??> | }
??- | ~

A trigraph is always treated as a single source character. The translation of trigraphs takes place in the first translation phase, before the recognition of escape characters in string literals and character constants. Only the nine trigraphs shown in Table 1.1 are recognized. All other character sequences are left untranslated.

The character escape sequence, \?, prevents the misinterpretation of trigraph-like character sequences. (For information about escape sequences, see Escape Sequences.) For example, if you attempt to print the string What??! with this printf statement

printf( "What??!\n" );

the string printed is What| because ??! is a trigraph sequence that is replaced with the | character. Write the statement as follows to correctly print the string:

printf( "What?\?!\n" );

In this printf statement, a backslash escape character in front of the second question mark prevents the misinterpretation of ??! as a trigraph.


C Constants

A “constant” is a number, character, or character string that can be used as a value in a program. Use constants to represent floating-point, integer, enumeration, or character values that cannot be modified.

Syntax

constant :

floating-point-constant
integer-constant
enumeration-constant
character-constant

Constants are characterized by having a value and a type. Floating-point, integer, and character constants are discussed in the next three sections. Enumeration constants are described in Enumeration Declarations in Chapter 3.


C Floating-Point Constants

A “floating-point constant” is a decimal number that represents a signed real number. The representation of a signed real number includes an integer portion, a fractional portion, and an exponent. Use floating-point constants to represent floating-point values that cannot be changed.

Syntax

floating-point-constant :

fractional-constant exponent-part opt floating-suffix opt
digit-sequence exponent-part floating-suffix opt

fractional-constant :

digit-sequence opt . digit-sequence
digit-sequence .

exponent-part :

e sign opt digit-sequence
E sign opt digit-sequence

sign : one of

+ –

digit-sequence :

digit
digit-sequence digit

floating-suffix : one of

f l F L

You can omit either the digits before the decimal point (the integer portion of the value) or the digits after the decimal point (the fractional portion), but not both. You can leave out the decimal point only if you include an exponent. No white-space characters can separate the digits or characters of the constant.

The following examples illustrate some forms of floating-point constants and expressions:

15.75
1.575E1   /* = 15.75   */
1575e-2   /* = 15.75   */
-2.5e-3   /* = -0.0025 */
25E-4     /* =  0.0025 */

Floating-point constants are positive unless they are preceded by a minus sign (–). In this case, the minus sign is treated as a unary arithmetic negation operator. Floating-point constants have type float, double, long, or long double.

A floating-point constant without an f, F, l, or L suffix has type double. If the letter f or F is the suffix, the constant has type float. If suffixed by the letter l or L, it has type long double. For example:

100L  /* Has type long double  */
100F  /* Has type float        */
100D  /* Has type double       */

Note that the Microsoft C compiler maps long double to type double. See Storage of Basic Types in Chapter 3 for information about type double, float, and long.

You can omit the integer portion of the floating-point constant, as shown in the following examples. The number .75 can be expressed in many ways, including the following:

.0075e2
0.075e1
.075e1
75e-2


Limits on Floating-Point Constants

Microsoft Specific —>

Limits on the values of floating-point constants are given in Table 1.2. The header file FLOAT.H contains this information.

Table 1.2 Limits on Floating-Point Constants

Constant | Meaning | Value
FLT_DIG DBL_DIG LDBL_DIG | Number of digits, q, such that a floating-point number with q decimal digits can be rounded into a floating-point representation and back without loss of precision. | 6 15 15
FLT_EPSILON DBL_EPSILON LDBL_EPSILON | Smallest positive number x, such that x + 1.0 is not equal to 1.0 | 1.192092896e–07F 2.2204460492503131e–016 2.2204460492503131e–016
FLT_GUARD |  | 0
FLT_MANT_DIG DBL_MANT_DIG LDBL_MANT_DIG | Number of digits in the radix specified by FLT_RADIX in the floating-point significand. The radix is 2; hence these values specify bits. | 24 53 53
FLT_MAX DBL_MAX LDBL_MAX | Maximum representable floating-point number. | 3.402823466e+38F 1.7976931348623158e+308 1.7976931348623158e+308
FLT_MAX_10_EXP DBL_MAX_10_EXP LDBL_MAX_10_EXP | Maximum integer such that 10 raised to that number is a representable floating-point number. | 38 308 308
FLT_MAX_EXP DBL_MAX_EXP LDBL_MAX_EXP | Maximum integer such that FLT_RADIX raised to that number is a representable floating-point number. | 128 1024 1024
FLT_MIN DBL_MIN LDBL_MIN | Minimum positive value. | 1.175494351e–38F 2.2250738585072014e–308 2.2250738585072014e–308
FLT_MIN_10_EXP DBL_MIN_10_EXP LDBL_MIN_10_EXP | Minimum negative integer such that 10 raised to that number is a representable floating-point number. | –37 –307 –307
FLT_MIN_EXP DBL_MIN_EXP LDBL_MIN_EXP | Minimum negative integer such that FLT_RADIX raised to that number is a representable floating-point number. | –125 –1021 –1021
FLT_NORMALIZE |  | 0
FLT_RADIX _DBL_RADIX _LDBL_RADIX | Radix of exponent representation. | 2 2 2
FLT_ROUNDS _DBL_ROUNDS _LDBL_ROUNDS | Rounding mode for floating-point addition. | 1 (near) 1 (near) 1 (near)

Note that the information in Table 1.2 may differ in future implementations.

END Microsoft Specific


C Integer Constants

An “integer constant” is a decimal (base 10), octal (base 8), or hexadecimal (base 16) number that represents an integral value. Use integer constants to represent integer values that cannot be changed.

Syntax

integer-constant :

decimal-constant integer-suffix opt
octal-constant integer-suffix opt
hexadecimal-constant integer-suffix opt

decimal-constant :

nonzero-digit
decimal-constant digit

octal-constant :

0
octal-constant octal-digit

hexadecimal-constant :

0x hexadecimal-digit
0X hexadecimal-digit
hexadecimal-constant hexadecimal-digit

nonzero-digit : one of

1 2 3 4 5 6 7 8 9

octal-digit : one of

0 1 2 3 4 5 6 7

hexadecimal-digit : one of

0 1 2 3 4 5 6 7 8 9
a b c d e f
A B C D E F

integer-suffix :

unsigned-suffix long-suffix opt
long-suffix unsigned-suffix opt

unsigned-suffix : one of

u U

long-suffix : one of

l L

64-bit integer-suffix :

i64

Integer constants are positive unless they are preceded by a minus sign (–). The minus sign is interpreted as the unary arithmetic negation operator. (See Unary Arithmetic Operators in Chapter 4 for information about this operator.)

If an integer constant begins with the letters 0x or 0X, it is hexadecimal. If it begins with the digit 0, it is octal. Otherwise, it is assumed to be decimal.

The following lines are equivalent:

0x1C   /* = Hexadecimal representation for decimal 28 */
034    /* = Octal representation for decimal 28 */

No white-space characters can separate the digits of an integer constant. These examples show valid decimal, octal, and hexadecimal constants.

/* Decimal Constants */
10
132
32179

/* Octal Constants */
012
0204
076663

/* Hexadecimal Constants */
0xa or 0xA
0x84
0x7dB3 or 0X7DB3


Integer Types

Every integer constant is given a type based on its value and the way it is expressed. You can force any integer constant to type long by appending the letter l or L to the end of the constant; you can force it to be type unsigned by appending u or U to the value. The lowercase letter l can be confused with the digit 1 and should be avoided. Some forms of long integer constants follow:

/* Long decimal constants */
10L
79L

/* Long octal constants */
012L
0115L

/* Long hexadecimal constants */
0xaL or 0xAL
0X4fL or 0x4FL

/* Unsigned long decimal constant */
776745UL
778866LU

The type you assign to a constant depends on the value the constant represents. A constant’s value must be in the range of representable values for its type. A constant’s type determines which conversions are performed when the constant is used in an expression or when the minus sign (–) is applied. This list summarizes the conversion rules for integer constants.

  • The type for a decimal constant without a suffix is either int, long int, or unsigned long int. The first of these three types in which the constant’s value can be represented is the type assigned to the constant.

  • The type assigned to octal and hexadecimal constants without suffixes is int, unsigned int, long int, or unsigned long int depending on the size of the constant.

  • The type assigned to constants with a u or U suffix is unsigned int or unsigned long int depending on their size.

  • The type assigned to constants with an l or L suffix is long int or unsigned long int depending on their size.

  • The type assigned to constants with a u or U and an l or L suffix is unsigned long int.


C Integer Limits

Microsoft Specific —>

The limits for integer types are listed in Table 1.3. These limits are defined in the standard header file LIMITS.H. Microsoft C also permits the declaration of sized integer variables, which are integral types of size 8-, 16-, or 32-bits. For more information on sized integers, see Sized Integer Types in Chapter 3.

Table 1.3 Limits on Integer Constants

Constant | Meaning | Value
CHAR_BIT | Number of bits in the smallest variable that is not a bit field. | 8
SCHAR_MIN | Minimum value for a variable of type signed char. | –128
SCHAR_MAX | Maximum value for a variable of type signed char. | 127
UCHAR_MAX | Maximum value for a variable of type unsigned char. | 255 (0xff)
CHAR_MIN | Minimum value for a variable of type char. | –128; 0 if /J option used
CHAR_MAX | Maximum value for a variable of type char. | 127; 255 if /J option used
MB_LEN_MAX | Maximum number of bytes in a multicharacter constant. | 2
SHRT_MIN | Minimum value for a variable of type short. | –32768
SHRT_MAX | Maximum value for a variable of type short. | 32767
USHRT_MAX | Maximum value for a variable of type unsigned short. | 65535 (0xffff)
INT_MIN | Minimum value for a variable of type int. | –2147483647 – 1
INT_MAX | Maximum value for a variable of type int. | 2147483647
UINT_MAX | Maximum value for a variable of type unsigned int. | 4294967295 (0xffffffff)
LONG_MIN | Minimum value for a variable of type long. | –2147483647 – 1
LONG_MAX | Maximum value for a variable of type long. | 2147483647
ULONG_MAX | Maximum value for a variable of type unsigned long. | 4294967295 (0xffffffff)

If a value exceeds the largest integer representation, the Microsoft compiler generates an error.

END Microsoft Specific


C Character Constants

A “character constant” is formed by enclosing a single character from the representable character set within single quotation marks (' '). Character constants are used to represent characters in the execution character set.

Syntax

character-constant :

'c-char-sequence'
L'c-char-sequence'

c-char-sequence :

c-char
c-char-sequence c-char

c-char :

Any member of the source character set except the single quotation mark ('), backslash (\), or newline character
escape-sequence

escape-sequence :

simple-escape-sequence
octal-escape-sequence
hexadecimal-escape-sequence

simple-escape-sequence : one of

\a \b \f \n \r \t \v
\' \" \\ \?

octal-escape-sequence :

\ octal-digit
\ octal-digit octal-digit
\ octal-digit octal-digit octal-digit

hexadecimal-escape-sequence :

\x hexadecimal-digit
hexadecimal-escape-sequence hexadecimal-digit


Character Types

An integer character constant not preceded by the letter L has type int. The value of an integer character constant containing a single character is the numerical value of the character interpreted as an integer. For example, the numerical value of the character a is 97 in decimal and 61 in hexadecimal.

Syntactically, a “wide-character constant” is a character constant prefixed by the letter L. A wide-character constant has type wchar_t, an integer type defined in the STDDEF.H header file. For example:

char    schar =  'x';   /* A character constant          */
wchar_t wchar = L'x';   /* A wide-character constant for
                            the same character           */

Wide-character constants are 16 bits wide and specify members of the extended execution character set. They allow you to express characters in alphabets that are too large to be represented by type char. See Multibyte and Wide Characters for more information about wide characters.


Execution Character Set

This book often refers to the “execution character set.” The execution character set is not necessarily the same as the source character set used for writing C programs. The execution character set includes all characters in the source character set as well as the null character, newline character, backspace, horizontal tab, vertical tab, carriage return, and escape sequences. The source and execution character sets may differ in other implementations.


Escape Sequences

Character combinations consisting of a backslash (\) followed by a letter or by a combination of digits are called “escape sequences.” To represent a newline character, single quotation mark, or certain other characters in a character constant, you must use escape sequences. An escape sequence is regarded as a single character and is therefore valid as a character constant.

Escape sequences are typically used to specify actions such as carriage returns and tab movements on terminals and printers. They are also used to provide literal representations of nonprinting characters and characters that usually have special meanings, such as the double quotation mark ("). Table 1.4 lists the ANSI escape sequences and what they represent.

Note that the question mark preceded by a backslash (\?) specifies a literal question mark in cases where the character sequence would be misinterpreted as a trigraph. See Trigraphs for more information.

Table 1.4 Escape Sequences

Escape Sequence | Represents
\a | Bell (alert)
\b | Backspace
\f | Formfeed
\n | New line
\r | Carriage return
\t | Horizontal tab
\v | Vertical tab
\' | Single quotation mark
\" | Double quotation mark
\\ | Backslash
\? | Literal question mark
\ooo | ASCII character in octal notation
\x hhh | ASCII character in hexadecimal notation

Microsoft Specific —>

If a backslash precedes a character that does not appear in Table 1.4, the compiler handles the undefined character as the character itself. For example, \x is treated as an x.

END Microsoft Specific

Escape sequences allow you to send nongraphic control characters to a display device. For example, the ESC character (\033) is often used as the first character of a control command for a terminal or printer. Some escape sequences are device-specific. For instance, the vertical-tab and formfeed escape sequences (\v and \f) do not affect screen output, but they do perform appropriate printer operations.

You can also use the backslash (\) as a continuation character. When a newline character (equivalent to pressing the RETURN key) immediately follows the backslash, the compiler ignores the backslash and the newline character and treats the next line as part of the previous line. This is useful primarily for preprocessor definitions longer than a single line. For example:

#define assert(exp) \
( (exp) ? (void) 0:_assert( #exp, __FILE__, __LINE__ ) )


Octal and Hexadecimal Character Specifications

The sequence \ooo means you can specify any character in the ASCII character set as a three-digit octal character code. The numerical value of the octal integer specifies the value of the desired character or wide character.

Similarly, the sequence \x hhh allows you to specify any ASCII character as a hexadecimal character code. For example, you can give the ASCII backspace character as the normal C escape sequence (\b), or you can code it as \010 (octal) or \x008 (hexadecimal).

You can use only the digits 0 through 7 in an octal escape sequence. Octal escape sequences can never be longer than three digits and are terminated by the first character that is not an octal digit. Although you do not need to use all three digits, you must use at least one. For example, the octal representation is \10 for the ASCII backspace character and \101 for the letter A, as given in an ASCII chart.

Similarly, you must use at least one digit for a hexadecimal escape sequence, but you can omit the second and third digits. Therefore you could specify the hexadecimal escape sequence for the backspace character as either \x8, \x08, or \x008.

The value of the octal or hexadecimal escape sequence must be in the range of representable values for type unsigned char for a character constant and type wchar_t for a wide-character constant. See Multibyte and Wide Characters for information on wide-character constants.

Unlike octal escape constants, the number of hexadecimal digits in an escape sequence is unlimited. A hexadecimal escape sequence terminates at the first character that is not a hexadecimal digit. Because hexadecimal digits include the letters a through f, care must be exercised to make sure the escape sequence terminates at the intended digit. To avoid confusion, you can place octal or hexadecimal character definitions in a macro definition:

#define Bell '\x07'

For hexadecimal values, you can break the string to show the correct value clearly:

"\xabc"    /* one character  */
"\xab" "c" /* two characters */


C String Literals

A “string literal” is a sequence of characters from the source character set enclosed in double quotation marks (" "). String literals are used to represent a sequence of characters which, taken together, form a null-terminated string. You must always prefix wide-string literals with the letter L.

Syntax

string-literal :

"s-char-sequence opt"
L"s-char-sequence opt"

s-char-sequence :

s-char
s-char-sequence s-char

s-char :

any member of the source character set except the double quotation mark ("), backslash (\), or newline character
escape-sequence

The example below is a simple string literal:

char amessage = "This is a string literal.";

All escape codes listed in Table 1.4 are valid in string literals. To represent a double quotation mark in a string literal, use the escape sequence \". The single quotation mark (') can be represented without an escape sequence. The backslash (\) must be followed with a second backslash (\\) when it appears within a string. When a backslash appears at the end of a line, it is always interpreted as a line-continuation character.


Type for String Literals

String literals have type array of char (that is, char[ ]). (Wide-character strings have type array of wchar_t (that is, wchar_t[ ]).) This means that a string is an array with elements of type char. The number of elements in the array is equal to the number of characters in the string plus one for the terminating null character.


Storage of String Literals

The characters of a literal string are stored in order at contiguous memory locations. An escape sequence (such as \\ or \") within a string literal counts as a single character. A null character (represented by the \0 escape sequence) is automatically appended to, and marks the end of, each string literal. (This occurs during translation phase 7. Note that the compiler may not store two identical strings at two different addresses. The /Gf (Eliminate Duplicate Strings) compiler option forces the compiler to place a single copy of identical strings into the executable file.

Microsoft Specific —>

Strings have static storage duration. See Storage Classes in Chapter 3 for information about storage duration.

END Microsoft Specific


String Literal Concatenation

To form string literals that take up more than one line, you can concatenate the two strings. To do this, type a backslash, then press the RETURN key. The backslash causes the compiler to ignore the following newline character. For example, the string literal

"Long strings can be bro\
ken into two or more pieces."

is identical to the string

"Long strings can be broken into two or more pieces."

String concatenation can be used anywhere you might previously have used a backslash followed by a newline character to enter strings longer than one line.

To force a new line within a string literal, enter the newline escape sequence (\n) at the point in the string where you want the line broken, as follows:

"Enter a number between 1 and 100\nOr press Return"

Because strings can start in any column of the source code and long strings can be continued in any column of a succeeding line, you can position strings to enhance source-code readability. In either case, their on-screen representation when output is unaffected. For example:

printf ( "This is the first half of the string, "
       "this is the second half ") ;

As long as each part of the string is enclosed in double quotation marks, the parts are concatenated and output as a single string. This concatenation occurs according to the sequence of events during compilation specified by translation phases.

"This is the first half of the string, this is the second half"

A string pointer, initialized as two distinct string literals separated only by white space, is stored as a single string (pointers are discussed in Pointer Declarations in Chapter 3). When properly referenced, as in the following example, the result is identical to the previous example:

char *string = "This is the first half of the string, "
         "this is the second half";

printf( "%s" , string ) ;

In translation phase 6, the multibyte-character sequences specified by any sequence of adjacent string literals or adjacent wide-string literals are concatenated into a single multibyte-character sequence. Therefore, do not design programs to allow modification of string literals during execution. The ANSI C standard specifies that the result of modifying a string is undefined.


Maximum String Length

Microsoft Specific —>

ANSI compatibility requires a compiler to accept up to 509 characters in a string literal after concatenation. The maximum length of a string literal allowed in Microsoft C is approximately 2,048 bytes. However, if the string literal consists of parts enclosed in double quotation marks, the preprocessor concatenates the parts into a single string, and for each line concatenated, it adds an extra byte to the total number of bytes.

For example, suppose a string consists of 40 lines with 50 characters per line (2,000 characters), and one line with 7 characters, and each line is surrounded by double quotation marks. This adds up to 2,007 bytes plus one byte for the terminating null character, for a total of 2,008 bytes. On concatenation, an extra character is added for each of the first 40 lines. This makes a total of 2,048 bytes. Note, however, that if line continuations (\) are used instead of double quotation marks, the preprocessor does not add an extra character for each line.

END Microsoft Specific


Punctuation and Special Characters

The punctuation and special characters in the C character set have various uses, from organizing program text to defining the tasks that the compiler or the compiled program carries out. They do not specify an operation to be performed. Some punctuation symbols are also operators (see Operators in Chapter 4). The compiler determines their use from context.

Syntax

punctuator : one of

[ ] ( ) { } * , : = ; ... #

These characters have special meanings in C. Their uses are described throughout this book. The pound sign (#) can occur only in preprocessing directives.


Program Structure

This chapter gives an overview of C programs and program execution. Terms and features important to understanding C programs and components are also introduced. Topics discussed include:

  • Source files and source programs

  • The main function and program execution

  • Parsing command-line arguments

  • Lifetime, scope, visibility, and linkage

  • Name spaces

Because this chapter is an overview, the topics discussed contain introductory material only. See the cross-referenced information for more detailed explanations.


Source Files and Source Programs

A source program can be divided into one or more “source files,” or “translation units.” The input to the compiler is called a “translation unit.”

Syntax

translation-unit :

external-declaration
translation-unit external-declaration

external-declaration :

function-definition
declaration

Overview of Declarations in Chapter 3 gives the syntax for the declaration nonterminal, and the Preprocessor Reference explains how the translation unit is processed.

Note See the introduction to Appendix A, C Language Syntax Summary, for an explanation of the ANSI syntax conventions.

The components of a translation unit are external declarations that include function definitions and identifier declarations. These declarations and definitions can be in source files, header files, libraries, and other files the program needs. You must compile each translation unit and link the resulting object files to make a program.

A C “source program” is a collection of directives, pragmas, declarations, definitions, statement blocks, and functions. To be valid components of a Microsoft C program, each must have the syntax described in this book, although they can appear in any order in the program (subject to the rules outlined throughout this book). However, the location of these components in a program does affect how variables and functions can be used in a program. (See Lifetime, Scope, Visibility, and Linkage for more information.)

Source files need not contain executable statements. For example, you may find it useful to place definitions of variables in one source file and then declare references to these variables in other source files that use them. This technique makes the definitions easy to find and update when necessary. For the same reason, constants and macros are often organized into separate files called “include files” or “header files” that can be referenced in source files as required. See the Preprocessor Reference for information about macros and include files.


Directives to the Preprocessor

A “directive” instructs the C preprocessor to perform a specific action on the text of the program before compilation. Preprocessor directives are fully described in the Preprocessor Reference. This example uses the preprocessor directive #define:

#define MAX 100

This statement tells the compiler to replace each occurrence of MAX by 100 before compilation. The C compiler preprocessor directives are:

#define | #endif | #ifdef | #line
#elif | #error | #ifndef | #pragma
#else | #if | #include | #undef


C Pragmas

Microsoft Specific —>

A “pragma” instructs the compiler to perform a particular action at compile time. Pragmas vary from compiler to compiler. For example, you can use the optimize pragma to set the optimizations to be performed on your program. The Microsoft C pragmas are:

alloc_text | data_seg | inline_recursion | setlocale
auto_inline | function | intrinsic | warning
check_stack | hdrstop | message |
code_seg | include_alias | optimize |
comment | inline_depth | pack |

See Chapter 2, Pragma Directives, in the Preprocessor Reference for a description of the Microsoft C compiler pragmas.

END Microsoft Specific


C Declarations and Definitions

A “declaration” establishes an association between a particular variable, function, or type and its attributes. Overview of Declarations in Chapter 3 gives the ANSI syntax for the declaration nonterminal. A declaration also specifies where and when an identifier can be accessed (the “linkage” of an identifier). See Lifetime, Scope, Visibility, and Linkage for information about linkage.

A “definition” of a variable establishes the same associations as a declaration but also causes storage to be allocated for the variable.

For example, the main, find, and count functions and the var and val variables are defined in one source file, in this order:

void main()
{
}

int var = 0;
double val[MAXVAL];

char find( fileptr )
{
}

int count( double f )
{
}

The variables var and val can be used in the find and count functions; no further declarations are needed. But these names are not visible (cannot be accessed) in main.


Function Declarations and Definitions

Function prototypes establish the name of the function, its return type, and the type and number of its formal parameters. A function definition includes the function body.

Both function and variable declarations can appear inside or outside a function definition. Any declaration within a function definition is said to appear at the “internal” or “local” level. A declaration outside all function definitions is said to appear at the “external,” “global,” or “file scope” level. Variable definitions, like declarations, can appear at the internal level (within a function definition) or at the external level (outside all function definitions). Function definitions always occur at the external level. Function definitions are discussed further in Function Definitions in Chapter 6. Function prototypes are covered in Function Prototypes in Chapter 6.


Blocks

A sequence of declarations, definitions, and statements enclosed within curly braces ({ }) is called a “block.” There are two types of blocks in C. The “compound statement,” a statement composed of one or more statements (see The Compound Statement in Chapter 5), is one type of block. The other, the “function definition,” consists of a compound statement (the body of the function) plus the function’s associated “header” (the function name, return type, and formal parameters). A block within other blocks is said to be “nested.”

Note that while all compound statements are enclosed within curly braces, not everything enclosed within curly braces constitutes a compound statement. For example, although the specifications of array, structure, or enumeration elements can appear within curly braces, they are not compound statements.


Example Program

The following C source program consists of two source files. It gives an overview of some of the various declarations and definitions possible in a C program. Later sections in this book describe how to write these declarations, definitions, and initializations, and how to use C keywords such as static and extern. The printf function is declared in the C header file STDIO.H.

The main and max functions are assumed to be in separate files, and execution of the program begins with the main function. No explicit user functions are executed before main.

/*****************************************************************
                    FILE1.C - main function
*****************************************************************/

#define ONE     1
#define TWO     2
#define THREE   3
#include <stdio.h>

int a = 1;                       /* Defining declarations     */
int b = 2;                       /*  of external variables    */

extern int max( int a, int b );  /* Function prototype        */

int main()                       /* Function definition       */
{                                /*  for main function        */
    int c;                       /* Definitions for           */
    int d;                       /*  two uninitialized        */
                                 /*  local variables          */

    extern int u;                /* Referencing declaration   */
                                 /*  of external variable     */
                                 /*  defined elsewhere        */
    static int v;                /* Definition of variable    */
                                 /*  with continuous lifetime */

    int w = ONE, x = TWO, y = THREE;
    int z = 0;
    z = max( x, y );             /* Executable statements     */
    w = max( z, w );
    printf( "%d %d\n", z, w );
    return 0;
}

/****************************************************************
            FILE2.C - definition of max function
****************************************************************/

int max( int a, int b )          /* Note formal parameters are   */
                                 /*  included in function header */
{
    if( a > b )
        return( a );
    else
        return( b );
}

FILE1.C contains the prototype for the max function. This kind of declaration is sometimes called a “forward declaration” because the function is declared before it is used. The definition for the main function includes calls to max.

The lines beginning with #define are preprocessor directives. These directives tell the preprocessor to replace the identifiers ONE, TWO, and THREE with the numbers 1, 2, and 3, respectively, throughout FILE1.C. However, the directives do not apply to FILE2.C, which is compiled separately and then linked with FILE1.C. The line beginning with #include tells the compiler to include the file STDIO.H, which contains the prototype for the printf function. Preprocessor directives are explained in the Preprocessor Reference.

FILE1.C uses defining declarations to initialize the global variables a and b. The local variables c and d are declared but not initialized. Storage is allocated for all these variables. The static and external variables, u and v, are automatically initialized to 0. Therefore only a, b, u, and v contain meaningful values when declared because they are initialized, either explicitly or implicitly. FILE2.C contains the function definition for max. This definition satisfies the calls to max in FILE1.C.

The lifetime and visibility of identifiers are discussed in Lifetime, Scope, Visibility, and Linkage. For more information on functions, see Chapter 6, Functions.


The main Function and Program Execution

Every C program has a primary (main) function that must be named main. If your code adheres to the Unicode programming model, you can use the wide-character version of main, wmain. The main function serves as the starting point for program execution. It usually controls program execution by directing the calls to other functions in the program. A program usually stops executing at the end of main, although it can terminate at other points in the program for a variety of reasons. At times, perhaps when a certain error is detected, you may want to force the termination of a program. To do so, use the exit function. See the Run-Time Library Reference for information on and an example using the exit function.

Functions within the source program perform one or more specific tasks. The main function can call these functions to perform their respective tasks. When main calls another function, it passes execution control to the function, so that execution begins at the first statement in the function. A function returns control to main when a return statement is executed or when the end of the function is reached.

You can declare any function, including main, to have parameters. The term “parameter” or “formal parameter” refers to the identifier that receives a value passed to a function. See Parameters in Chapter 6 for information on passing arguments to parameters. When one function calls another, the called function receives values for its parameters from the calling function. These values are called “arguments.” You can declare formal parameters to main so that it can receive arguments from the command line using this format:

main( int argc, char *argv[ ], char *envp[ ] )

When you want to pass information to the main function, the parameters are traditionally named argc and argv, although the C compiler does not require these names. The types for argc and argv are defined by the C language. Traditionally, if a third parameter is passed to main, that parameter is named envp. Examples later in this chapter show how to use these three parameters to access command-line arguments. The following sections explain these parameters.

See Using wmain for a description of the wide-character version of main.


Using wmain

Microsoft Specific —>

In the Unicode programming model, you can define a wide-character version of the main function. Use wmain instead of main if you want to write portable code that adheres to the Unicode programming model.

You declare formal parameters to wmain using a similar format to main. You can then pass wide-character arguments and, optionally, a wide-character environment pointer to the program. The argv and envp parameters to wmain are of type wchar_t*. For example:

wmain( int argc, wchar_t *argv[ ], wchar_t *envp[ ] )

If your program uses a main function, the multibyte-character environment is created by the run-time library at program startup. A wide-character copy of the environment is created only when needed (for example, by a call to the _wgetenv or _wputenv functions). On the first call to _wputenv, or on the first call to _wgetenv if an MBCS environment already exists, a corresponding wide-character string environment is created and is then pointed to by the _wenviron global variable, which is a wide-character version of the _environ global variable. At this point, two copies of the environment (MBCS and Unicode) exist simultaneously and are maintained by the operating system throughout the life of the program.

Similarly, if your program uses a wmain function, a wide-character environment is created at program startup and is pointed to by the _wenviron global variable. An MBCS (ASCII) environment is created on the first call to _putenv or getenv, and is pointed to by the _environ global variable.

For more information on the MBCS environment, see Internationalization in the Run-Time Library Reference.

END Microsoft Specific


Argument Description

The argc parameter in the main and wmain functions is an integer specifying how many arguments are passed to the program from the command line. Since the program name is considered an argument, the value of argc is at least one.

The argv parameter is an array of pointers to null-terminated strings representing the program arguments. Each element of the array points to a string representation of an argument passed to main (or wmain). (For information about arrays, see Array Declarations in Chapter 3.) The argv parameter can be declared either as an array of pointers to type char (char *argv[]) or as a pointer to pointers to type char (char **argv). For wmain, the argv parameter can be declared either as an array of pointers to type wchar_t (wchar_t *argv[]) or as a pointer to pointers to type wchar_t (wchar_t **argv). The first string (argv[0]) is the program name. The last pointer (argv[argc]) is NULL. (See getenv in the Run-Time Library Reference for an alternative method for getting environment variable information.)

Microsoft Specific —>

The envp parameter is a pointer to an array of null-terminated strings that represent the values set in the user’s environment variables. The envp parameter can be declared as an array of pointers to char (char *envp[]) or as a pointer to pointers to char (char **envp). In a wmain function, the envp parameter can be declared as an array of pointers to wchar_t (wchar_t *envp[]) or as a pointer to pointers to wchar_t (wchar_t **envp). The end of the array is indicated by a NULL *pointer. Note that the environment block passed to main or wmain is a “frozen” copy of the current environment. If you subsequently change the environment via a call to _putenv or _wputenv, the current environment (as returned by getenv/_wgetenv and the _environ or _wenviron variables) will change, but the block pointed to by envp will not change. The envp parameter is ANSI compatible in C, but not in C++.

END Microsoft Specific


Expanding Wildcard Arguments

Microsoft Specific —>

When running a C program, you can use either of the two wildcards — the question mark (?) and the asterisk (*) — to specify filename and path arguments on the command line.

Command-line arguments are handled by a routine called _setargv (or _wsetargv in the wide-character environment), which by default does not expand wildcards into separate strings in the argv string array. You can replace the normal _setargv routine with a more powerful version of _setargv that does handle wildcards by linking with the Setargv.obj file. If your program uses a wmain function, link with Wsetargv.obj.

To link with Setargv.obj or Wsetargv.obj, use the /link option. For example:

cl typeit.c /link setargv.obj

The wildcards are expanded in the same manner as operating system commands. (See your operating system user’s guide if you are unfamiliar with wildcards.) Enclosing an argument in double quotation marks (" ") suppresses the wildcard expansion. Within quoted arguments, you can represent quotation marks literally by preceding the double-quotation-mark character with a backslash (\). If no matches are found for the wildcard argument, the argument is passed literally.

END Microsoft Specific


Parsing C Command-Line Arguments

Microsoft Specific —>

Microsoft C startup code uses the following rules when interpreting arguments given on the operating system command line:

  • Arguments are delimited by white space, which is either a space or a tab.

  • A string surrounded by double quotation marks is interpreted as a single argument, regardless of white space contained within. A quoted string can be embedded in an argument. Note that the caret (^) is not recognized as an escape character or delimiter.

  • A double quotation mark preceded by a backslash, \", is interpreted as a literal double quotation mark (").

  • Backslashes are interpreted literally, unless they immediately precede a double quotation mark.

  • If an even number of backslashes is followed by a double quotation mark, then one backslash (\) is placed in the argv array for every pair of backslashes (\\), and the double quotation mark (") is interpreted as a string delimiter.

  • If an odd number of backslashes is followed by a double quotation mark, then one backslash (\) is placed in the argv array for every pair of backslashes (\\) and the double quotation mark is interpreted as an escape sequence by the remaining backslash, causing a literal double quotation mark (") to be placed in argv.

This list illustrates the rules above by showing the interpreted result passed to argv for several examples of command-line arguments. The output listed in the second, third, and fourth columns is from the ARGS.C program that follows the list.

Command-Line Input | argv[1] | argv[2] | argv[3]
"a b c" d e | a b c | d | e
"ab\"c" "\\" d | ab"c | \ | d
a\\\b d"e f"g h | a\\\b | de fg | h
a\\\"b c d | a\"b | c | d
a\\\\"b c" d e | a\\b c | d | e

/* ARGS.C illustrates the following variables used for accessing
 * command-line arguments and environment variables:
 * argc  argv  envp
 */

#include <stdio.h>

void main( int argc, /* Number of strings in array argv */
 char *argv[],       /* Array of command-line argument strings */
 char **envp )       /* Array of environment variable strings */
{
    int count;

    /* Display each command-line argument. */
    printf( "\nCommand-line arguments:\n" );
    for( count = 0; count < argc; count++ )
        printf( "  argv[%d]   %s\n", count, argv[count] );

    /* Display each environment variable. */
    printf( "\nEnvironment variables:\n" );
    while( *envp != NULL )
        printf( "  %s\n", *(envp++) );

    return;
}

One example of output from this program is:

Command-line arguments:
  argv[0]   C:\MSC\TEST.EXE

Environment variables:
  COMSPEC=C:\NT\SYSTEM32\CMD.EXE

  PATH=c:\nt;c:\binb;c:\binr;c:\nt\system32;c:\word;c:\help;c:\msc;c:\;
  PROMPT=[$p]
  TEMP=c:\tmp
  TMP=c:\tmp
  EDITORS=c:\binr
  WINDIR=c:\nt

END Microsoft Specific


Customizing C Command-Line Processing

If your program does not take command-line arguments, you can save a small amount of space by suppressing use of the library routine that performs command-line processing. This routine is called _setargv (or _wsetargv in the wide-character environment), as described in Expanding Wildcard Arguments. To suppress its use, define a routine that does nothing in the file containing the main function and name it _setargv (or _wsetargv in the wide-character environment). The call to _setargv or _wsetargv is then satisfied by your definition of _setargv or _wsetargv , and the library version is not loaded.

Similarly, if you never access the environment table through the envp argument, you can provide your own empty routine to be used in place of _setenvp (or _wsetenvp), the environment-processing routine.

If your program makes calls to the _spawn or _exec family of routines in the C run-time library, you should not suppress the environment-processing routine, since this routine is used to pass an environment from the spawning process to the new process.


Lifetime, Scope, Visibility, and Linkage

To understand how a C program works, you must understand the rules that determine how variables and functions can be used in the program. Several concepts are crucial to understanding these rules:

  • Lifetime

  • Scope and visibility

  • Linkage


Lifetime

“Lifetime” is the period during execution of a program in which a variable or function exists. The storage duration of the identifier determines its lifetime.

An identifier declared with the storage-class-specifier static has static storage duration. Identifiers with static storage duration (also called “global”) have storage and a defined value for the duration of a program. Storage is reserved and the identifier’s stored value is initialized only once, before program startup. An identifier declared with external or internal linkage also has static storage duration (see Linkage).

An identifier declared without the static storage-class specifier has automatic storage duration if it is declared inside a function. An identifier with automatic storage duration (a “local identifier”) has storage and a defined value only within the block where the identifier is defined or declared. An automatic identifier is allocated new storage each time the program enters that block, and it loses its storage (and its value) when the program exits the block. Identifiers declared in a function with no linkage also have automatic storage duration.

The following rules specify whether an identifier has global (static) or local (automatic) lifetime:

  • All functions have static lifetime. Therefore they exist at all times during program execution. Identifiers declared at the external level (that is, outside all blocks in the program at the same level of function definitions) always have global (static) lifetimes.

  • If a local variable has an initializer, the variable is initialized each time it is created (unless it is declared as static). Function parameters also have local lifetime. You can specify global lifetime for an identifier within a block by including the static storage-class specifier in its declaration. Once declared static, the variable retains its value from one entry of the block to the next.

Although an identifier with a global lifetime exists throughout the execution of the source program (for example, an externally declared variable or a local variable declared with the static keyword), it may not be visible in all parts of the program. See Scope and Visibility for information about visibility, and see Storage Classes in Chapter 3 for a discussion of the storage-class-specifier nonterminal.

Memory can be allocated as needed (dynamic) if created through the use of special library routines such as malloc. Since dynamic memory allocation uses library routines, it is not considered part of the language. See the malloc function in the Run-Time Library Reference.


Scope and Visibility

An identifier’s “visibility” determines the portions of the program in which it can be referenced—its “scope.” An identifier is visible (i.e., can be used) only in portions of a program encompassed by its “scope,” which may be limited (in order of increasing restrictiveness) to the file, function, block, or function prototype in which it appears. The scope of an identifier is the part of the program in which the name can be used. This is sometimes called “lexical scope.” There are four kinds of scope: function, file, block, and function prototype.

All identifiers except labels have their scope determined by the level at which the declaration occurs. The following rules for each kind of scope govern the visibility of identifiers within a program:

File scope

The declarator or type specifier for an identifier with file scope appears outside any block or list of parameters and is accessible from any place in the translation unit after its declaration. Identifier names with file scope are often called “global” or “external.” The scope of a global identifier begins at the point of its definition or declaration and terminates at the end of the translation unit.

Function scope

A label is the only kind of identifier that has function scope. A label is declared implicitly by its use in a statement. Label names must be unique within a function. (For more information about labels and label names, see The goto and Labeled Statements in Chapter 5.)

Block scope

The declarator or type specifier for an identifier with block scope appears inside a block or within the list of formal parameter declarations in a function definition. It is visible only from the point of its declaration or definition to the end of the block containing its declaration or definition. Its scope is limited to that block and to any blocks nested in that block and ends at the curly brace that closes the associated block. Such identifiers are sometimes called “local variables.”

Function-prototype scope

The declarator or type specifier for an identifier with function-prototype scope appears within the list of parameter declarations in a function prototype (not part of the function declaration). Its scope terminates at the end of the function declarator.

The appropriate declarations for making variables visible in other source files are described in Storage Classes in Chapter 3. However, variables and functions declared at the external level with the static storage-class specifier are visible only within the source file in which they are defined. All other functions are globally visible.


Summary of Lifetime and Visibility

Table 2.1 is a summary of lifetime and visibility characteristics for most identifiers. The first three columns give the attributes that define lifetime and visibility. An identifier with the attributes given by the first three columns has the lifetime and visibility shown in the fourth and fifth columns. However, the table does not cover all possible cases. Refer to Storage Classes in Chapter 3 for more information.

Table 2.1 Summary of Lifetime and Visibility

Attributes: Level | Item | Storage-Class Specifier | Result: Lifetime | Visibility
File scope | Variable definition | static | Global | Remainder of source file in which it occurs
 | Variable declaration | extern | Global | Remainder of source file in which it occurs
 | Function prototype or definition | static | Global | Single source file
 | Function prototype | extern | Global | Remainder of source file
Block scope | Variable declaration | extern | Global | Block
 | Variable definition | static | Global | Block
 | Variable definition | auto or register | Local | Block

The following example illustrates blocks, nesting, and visibility of variables:

#include <stdio.h>

int i = 1;               /* i defined at external level               */

int main()               /* main function defined at external level   */
{
    printf( "%d\n", i ); /* Prints 1 (value of external level i)      */
    {                            /* Begin first nested block          */
        int i = 2, j = 3;        /* i and j defined at internal level */
        printf( "%d %d\n", i, j );     /* Prints 2, 3                 */
        {                        /* Begin second nested block         */
            int i = 0;           /* i is redefined                    */
            printf( "%d %d\n", i, j ); /* Prints 0, 3                 */
        }                        /* End of second nested block        */
        printf( "%d\n", i );     /* Prints 2 (outer definition        */
                                 /*  restored)                        */
    }                            /* End of first nested block         */
    printf( "%d\n", i );         /* Prints 1 (external level          */
                                 /* definition restored)              */
    return 0;
}

In this example, there are four levels of visibility: the external level and three block levels. The values are printed to the screen as noted in the comments following each statement.


Linkage

Identifier names can refer to different identifiers in different scopes. An identifier declared in different scopes or in the same scope more than once can be made to refer to the same identifier or function by a process called “linkage.” Linkage determines the portions of the program in which an identifier can be referenced (its “visibility”). There are three kinds of linkage: internal, external, and no linkage.


Internal Linkage

If the declaration of a file-scope identifier for an object or a function contains the storage-class-specifier static, the identifier has internal linkage. Otherwise, the identifier has external linkage. See Storage Classes in Chapter 3 for a discussion of the storage-class-specifier nonterminal.

Within one translation unit, each instance of an identifier with internal linkage denotes the same identifier or function. Internally linked identifiers are unique to a translation unit.


External Linkage

If the first declaration at file-scope level for an identifier does not use the static storage-class specifier, the object has external linkage.

If the declaration of an identifier for a function has no storage-class-specifier, its linkage is determined exactly as if it were declared with the storage-class-specifier extern. If the declaration of an identifier for an object has file scope and no storage-class-specifier, its linkage is external.

An identifier’s name with external linkage designates the same function or data object as does any other declaration for the same name with external linkage. The two declarations can be in the same translation unit or in different translation units. If the object or function also has global lifetime, the object or function is shared by the entire program.


No Linkage

If a declaration for an identifier within a block does not include the extern storage-class specifier, the identifier has no linkage and is unique to the function.

The following identifiers have no linkage:

  • An identifier declared to be anything other than an object or a function

  • An identifier declared to be a function parameter

  • A block-scope identifier for an object declared without the extern storage-class specifier

If an identifier has no linkage, declaring the same name again (in a declarator or type specifier) in the same scope level generates a symbol redefinition error.


Name Spaces

The compiler sets up “name spaces” to distinguish between the identifiers used for different kinds of items. The names within each name space must be unique to avoid conflict, but an identical name can appear in more than one name space. This means that you can use the same identifier for two or more different items, provided that the items are in different name spaces. The compiler can resolve references based on the syntactic context of the identifier in the program.

Note Do not confuse the limited C notion of a name space with the C++ “namespace” feature. See Namespaces in the C++ Language Reference for more information.

This list describes the name spaces used in C.

Statement labels

Named statement labels are part of statements. Definitions of statement labels are always followed by a colon but are not part of case labels. Uses of statement labels always immediately follow the keyword goto. Statement labels do not have to be distinct from other names or from label names in other functions.

Structure, union, and enumeration tags

These tags are part of structure, union, and enumeration type specifiers and, if present, always immediately follow the reserved words struct, union, or enum. The tag names must be distinct from all other structure, enumeration, or union tags with the same visibility.

Members of structures or unions

Member names are allocated in name spaces associated with each structure and union type. That is, the same identifier can be a component name in any number of structures or unions at the same time. Definitions of component names always occur within structure or union type specifiers. Uses of component names always immediately follow the member-selection operators (–> and .). The name of a member must be unique within the structure or union, but it does not have to be distinct from other names in the program, including the names of members of different structures and unions, or the name of the structure itself.

Ordinary identifiers

All other names fall into a name space that includes variables, functions (including formal parameters and local variables), and enumeration constants. Identifier names have nested visibility, so you can redefine them within blocks.

Typedef names

Typedef names cannot be used as identifiers in the same scope.

For example, since structure tags, structure members, and variable names are in three different name spaces, the three items named student in this example do not conflict. The context of each item allows correct interpretation of each occurrence of student in the program. (For information about structures, see Structure Declarations in Chapter 3.)

struct student {
   char student[20];
   int class;
   int id;
   } student;

When student appears after the struct keyword, the compiler recognizes it as a structure tag. When student appears after a member-selection operator (–> or .), the name refers to the structure member. In other contexts, student refers to the structure variable. However, overloading the tag name space is not recommended since it obscures meaning.


Declarations and Types

This chapter describes the declaration and initialization of variables, functions, and types. The C language includes a standard set of basic data types. You can also add your own data types, called “derived types,” by declaring new ones based on types already defined. The following topics are discussed:

  • Overview of declarations

  • Storage classes

  • Type specifiers

  • Type qualifiers

  • Declarators and variable declarations

  • Interpreting more complex declarators

  • Initialization

  • Storage of basic types

  • Incomplete types

  • Typedef declarations

  • Extended storage-class attributes


Overview of Declarations

A “declaration” specifies the interpretation and attributes of a set of identifiers. A declaration that also causes storage to be reserved for the object or function named by the identifier is called a “definition.” C declarations for variables, functions, and types have this syntax:

Syntax

declaration :

declaration-specifiers init-declarator-list opt ;

declaration-specifiers :

storage-class-specifier attribute-seq opt declaration-specifiers opt
/* attribute-seq opt is Microsoft specific */
type-specifier declaration-specifiers opt
type-qualifier declaration-specifiers opt

init-declarator-list :

init-declarator
init-declarator-list , init-declarator

init-declarator :

declarator
declarator = initializer

Note This syntax for declaration is not repeated in the following sections. Syntax in the following sections usually begin with the declarator nonterminal.

The declarations in the init-declarator-list contain the identifiers being named; init is an abbreviation for initializer. The init-declarator-list is a comma-separated sequence of declarators, each of which can have additional type information, or an initializer, or both. The declarator contains the identifiers, if any, being declared. The declaration-specifiers nonterminal consists of a sequence of type and storage-class specifiers that indicate the linkage, storage duration, and at least part of the type of the entities that the declarators denote. Therefore, declarations are made up of some combination of storage-class specifiers, type specifiers, type qualifiers, declarators, and initializers.

Declarations can contain one or more of the optional attributes listed in attribute-seq; seq is an abbreviation for sequence. These Microsoft-specific attributes perform a variety of functions, which are discussed in detail throughout this book. For a list of these attributes, see Appendix A, C Language Syntax Summary.

In the general form of a variable declaration, type-specifier gives the data type of the variable. The type-specifier can be a compound, as when the type is modified by const or volatile. The declarator gives the name of the variable, possibly modified to declare an array or a pointer type. For example,

int const *fp;

declares a variable named fp as a pointer to a nonmodifiable (const) int value. You can define more than one variable in a declaration by using multiple declarators, separated by commas.

A declaration must have at least one declarator, or its type specifier must declare a structure tag, union tag, or members of an enumeration. Declarators provide any remaining information about an identifier. A declarator is an identifier that can be modified with brackets ([ ]), asterisks (*), or parentheses ( ( ) ) to declare an array, pointer, or function type, respectively. When you declare simple variables (such as character, integer, and floating-point items), or structures and unions of simple variables, the declarator is just an identifier. For more information on declarators, see Declarators and Variable Declarations.

All definitions are implicitly declarations, but not all declarations are definitions. For example, variable declarations that begin with the extern storage-class specifier are “referencing,” rather than “defining” declarations. If an external variable is to be referred to before it is defined, or if it is defined in another source file from the one where it is used, an extern declaration is necessary. Storage is not allocated by “referencing” declarations, nor can variables be initialized in declarations.

A storage class or a type (or both) is required in variable declarations. Except for __declspec, only one storage-class specifier is allowed in a declaration and not all storage-class specifiers are permitted in every context. The __declspec storage class is allowed with other storage-class specifiers, and it is allowed more than once. The storage-class specifier of a declaration affects how the declared item is stored and initialized, and which parts of a program can reference the item.

The storage-class-specifier terminals defined in C include auto, extern, register, static, and typedef. In addition, Microsoft C includes the storage-class-specifier terminal __declspec. All storage-class-specifier terminals except typedef and __declspec are discussed in Storage Classes. See Typedef Declarations for information about typedef. See Extended Storage-Class Attributes for information about __declspec.

The location of the declaration within the source program and the presence or absence of other declarations of the variable are important factors in determining the lifetime of variables. There can be multiple redeclarations but only one definition. However, a definition can appear in more than one translation unit. For objects with internal linkage, this rule applies separately to each translation unit, because internally linked objects are unique to a translation unit. For objects with external linkage, this rule applies to the entire program. See Lifetime, Scope, Visibility, and Linkage in Chapter 2 for more information about visibility.

Type specifiers provide some information about the data types of identifiers. The default type specifier is int. For more information, see Type Specifiers. Type specifiers can also define type tags, structure and union component names, and enumeration constants. For more information see Enumeration Declarations, Structure Declarations, and Union Declarations.

There are two type-qualifier terminals: const and volatile. These qualifiers specify additional properties of types that are relevant only when accessing objects of that type through l-values. For more information on const and volatile, see Type Qualifiers. For a definition of l-values, see L-Value and R-Value Expressions in Chapter 4.


C Storage Classes

The “storage class” of a variable determines whether the item has a “global” or “local” lifetime. C calls these two lifetimes “static” and “automatic.” An item with a global lifetime exists and has a value throughout the execution of the program. All functions have global lifetimes.

Automatic variables, or variables with local lifetimes, are allocated new storage each time execution control passes to the block in which they are defined. When execution returns, the variables no longer have meaningful values.

C provides the following storage-class specifiers:

Syntax

storage-class-specifier :

auto
register
static
extern
typedef
__declspec ( extended-decl-modifier-seq ) /* Microsoft Specific */

Except for __declspec, you can use only one storage-class-specifier in the declaration-specifier in a declaration. If no storage-class specification is made, declarations within a block create automatic objects.

Items declared with the auto or register specifier have local lifetimes. Items declared with the static or extern specifier have global lifetimes.

Since typedef and __declspec are semantically different from the other four storage-class-specifier terminals, they are discussed separately. For specific information on typedef, see Typedef Declarations. For specific information on __declspec, see Extended Storage-Class Attributes.

The placement of variable and function declarations within source files also affects storage class and visibility. Declarations outside all function definitions are said to appear at the “external level.” Declarations within function definitions appear at the “internal level.”

The exact meaning of each storage-class specifier depends on two factors:

  • Whether the declaration appears at the external or internal level

  • Whether the item being declared is a variable or a function

Storage-Class Specifiers for External-Level Declarations and Storage-Class Specifiers for Internal-Level Declarations describe the storage-class-specifier terminals in each kind of declaration and explain the default behavior when the storage-class-specifier is omitted from a variable. Storage-Class Specifiers with Function Declarations discusses storage-class specifiers used with functions.


Storage-Class Specifiers for External-Level Declarations

External variables are variables at file scope. They are defined outside any function, and they are potentially available to many functions. Functions can only be defined at the external level and, therefore, cannot be nested. By default, all references to external variables and functions of the same name are references to the same object, which means they have “external linkage.” (You can use the static keyword to override this. See information later in this section for more details on static.)

Variable declarations at the external level are either definitions of variables (“defining declarations”), or references to variables defined elsewhere (“referencing declarations”).

An external variable declaration that also initializes the variable (implicitly or explicitly) is a defining declaration of the variable. A definition at the external level can take several forms:

  • A variable that you declare with the static storage-class specifier. You can explicitly initialize the static variable with a constant expression, as described in Initialization. If you omit the initializer, the variable is initialized to 0 by default. For example, these two statements are both considered definitions of the variable k.
    static int k = 16;
static int k;
  • A variable that you explicitly initialize at the external level. For example, int j = 3; is a definition of the variable j.

In variable declarations at the external level (that is, outside all functions), you can use the static or extern storage-class specifier or omit the storage-class specifier entirely. You cannot use the auto and register storage-class-specifier terminals at the external level.

Once a variable is defined at the external level, it is visible throughout the rest of the translation unit. The variable is not visible prior to its declaration in the same source file. Also, it is not visible in other source files of the program, unless a referencing declaration makes it visible, as described below.

The rules relating to static include:

  • Variables declared outside all blocks without the static keyword always retain their values throughout the program. To restrict their access to a particular translation unit, you must use the static keyword. This gives them “internal linkage.” To make them global to an entire program, omit the explicit storage class or use the keyword extern (see the rules in the next list). This gives them “external linkage.” Internal and external linkage are also discussed in Linkage in Chapter 2.

  • You can define a variable at the external level only once within a program. You can define another variable with the same name and the static storage-class specifier in a different translation unit. Since each static definition is visible only within its own translation unit, no conflict occurs. This provides a useful way to hide identifier names that must be shared among functions of a single translation unit, but not visible to other translation units.

  • The static storage-class specifier can apply to functions as well. If you declare a function static, its name is invisible outside of the file in which it is declared.

The rules for using extern are:

  • The extern storage-class specifier declares a reference to a variable defined elsewhere. You can use an extern declaration to make a definition in another source file visible, or to make a variable visible prior to its definition in the same source file. Once you have declared a reference to the variable at the external level, the variable is visible throughout the remainder of the translation unit in which the declared reference occurs.

  • For an extern reference to be valid, the variable it refers to must be defined once, and only once, at the external level. This definition (without the extern storage class) can be in any of the translation units that make up the program.

Example

The example below illustrates external declarations:

/******************************************************************
                      SOURCE FILE ONE
*******************************************************************/

extern int i;                /* Reference to i, defined below */
void next( void );           /* Function prototype            */

void main()
{
    i++;
    printf( "%d\n", i );     /* i equals 4 */
    next();
}

int i = 3;                   /* Definition of i */

void next( void )
{
    i++;
    printf( "%d\n", i );     /* i equals 5 */
    other();
}

/******************************************************************
                      SOURCE FILE TWO
*******************************************************************/

extern int i;                /* Reference to i in  */
                             /* first source file  */
void other( void )
{
    i++;
    printf( "%d\n", i );     /* i equals 6 */
}

The two source files in this example contain a total of three external declarations of i. Only one declaration is a “defining declaration.” That declaration,

int i = 3;

defines the global variable i and initializes it with initial value 3. The “referencing” declaration of i at the top of the first source file using extern makes the global variable visible prior to its defining declaration in the file. The referencing declaration of i in the second source file also makes the variable visible in that source file. If a defining instance for a variable is not provided in the translation unit, the compiler assumes there is an

extern int x;

referencing declaration and that a defining reference

int x = 0;

appears in another translation unit of the program.

All three functions, main, next, and other, perform the same task: they increase i and print it. The values 4, 5, and 6 are printed.

If the variable i had not been initialized, it would have been set to 0 automatically. In this case, the values 1, 2, and 3 would have been printed. See Initialization for information about variable initialization.


Storage-Class Specifiers for Internal-Level Declarations

You can use any of four storage-class-specifier terminals for variable declarations at the internal level. When you omit the storage-class-specifier from such a declaration, the default storage class is auto. Therefore, the keyword auto is rarely seen in a C program.


The auto Storage-Class Specifier

The auto storage-class specifier declares an automatic variable, a variable with a local lifetime. An auto variable is visible only in the block in which it is declared. Declarations of auto variables can include initializers, as discussed in Initialization. Since variables with auto storage class are not initialized automatically, you should either explicitly initialize them when you declare them, or assign them initial values in statements within the block. The values of uninitialized auto variables are undefined. (A local variable of auto or register storage class is initialized each time it comes in scope if an initializer is given.)

An internal static variable (a static variable with local or block scope) can be initialized with the address of any external or static item, but not with the address of another auto item, because the address of an auto item is not a constant.


The register Storage-Class Specifier

Microsoft Specific —>

The Microsoft C/C++ compiler does not honor user requests for register variables. However, for portability all other semantics associated with the register keyword are honored by the compiler. For example, you cannot apply the unary address-of operator (&) to a register object nor can the register keyword be used on arrays.

END Microsoft Specific


The static Storage-Class Specifier

A variable declared at the internal level with the static storage-class specifier has a global lifetime but is visible only within the block in which it is declared. For constant strings, using static is useful because it alleviates the overhead of frequent initialization in often-called functions.

If you do not explicitly initialize a static variable, it is initialized to 0 by default. Inside a function, static causes storage to be allocated and serves as a definition. Internal static variables provide private, permanent storage visible to only a single function.


The extern Storage-Class Specifier

A variable declared with the extern storage-class specifier is a reference to a variable with the same name defined at the external level in any of the source files of the program. The internal extern declaration is used to make the external-level variable definition visible within the block. Unless otherwise declared at the external level, a variable declared with the extern keyword is visible only in the block in which it is declared.

Example

This example illustrates internal- and external-level declarations:

#include <stdio.h>
int i = 1;
void other( void );

void main()
{
    /* Reference to i, defined above: */
    extern int i;

    /* Initial value is zero; a is visible only within main: */
    static int a;

    /* b is stored in a register, if possible: */
    register int b = 0;

    /* Default storage class is auto: */
    int c = 0;

    /* Values printed are 1, 0, 0, 0: */
    printf( "%d\n%d\n%d\n%d\n", i, a, b, c );
    other();
    return;
}

void other( void )
{
    /* Address of global i assigned to pointer variable: */
    static int *external_i = &i;

    /* i is redefined; global i no longer visible: */
    int i = 16;

    /* This a is visible only within the other function: */
    static int a = 2;

    a += 2;
    /* Values printed are 16, 4, and 1: */
    printf( "%d\n%d\n%d\n", i, a, *external_i );
}

In this example, the variable i is defined at the external level with initial value 1. An extern declaration in the main function is used to declare a reference to the external-level i. The static variable a is initialized to 0 by default, since the initializer is omitted. The call to printf prints the values 1, 0, 0, and 0.

In the other function, the address of the global variable i is used to initialize the static pointer variable external_i. This works because the global variable has static lifetime, meaning its address does not change during program execution. Next, the variable i is redefined as a local variable with initial value 16. This redefinition does not affect the value of the external-level i, which is hidden by the use of its name for the local variable. The value of the global i is now accessible only indirectly within this block, through the pointer external_i. Attempting to assign the address of the auto variable i to a pointer does not work, since it may be different each time the block is entered. The variable a is declared as a static variable and initialized to 2. This a does not conflict with the a in main, since static variables at the internal level are visible only within the block in which they are declared.

The variable a is increased by 2, giving 4 as the result. If the other function were called again in the same program, the initial value of a would be 4. Internal static variables keep their values when the program exits and then reenters the block in which they are declared.


Storage-Class Specifiers with Function Declarations

You can use either the static or the extern storage-class specifier in function declarations. Functions always have global lifetimes.

Microsoft Specific —>

Function declarations at the internal level have the same meaning as function declarations at the external level. This means that a function is visible from its point of declaration throughout the rest of the translation unit even if it is declared at local scope.

END Microsoft Specific

The visibility rules for functions vary slightly from the rules for variables, as follows:

  • A function declared to be static is visible only within the source file in which it is defined. Functions in the same source file can call the static function, but functions in other source files cannot access it directly by name. You can declare another static function with the same name in a different source file without conflict.

  • Functions declared as extern are visible throughout all source files in the program (unless you later redeclare such a function as static). Any function can call an extern function.

  • Function declarations that omit the storage-class specifier are extern by default.

Microsoft Specific —>

Microsoft allows redefinition of an extern identifier as static.

END Microsoft Specific


C Type Specifiers

Type specifiers in declarations define the type of a variable or function declaration.

Syntax

type-specifier :

void
char
short
int
long
float
double
signed
unsigned
struct-or-union-specifier
enum-specifier
typedef-name

The signed char, signed int, signed short int, and signed long int types, together with their unsigned counterparts and enum, are called “integral” types. The float, double, and long double type specifiers are referred to as “floating” or “floating-point” types. You can use any integral or floating-point type specifier in a variable or function declaration. If a type-specifier is not provided in a declaration, it is taken to be int.

The optional keywords signed and unsigned can precede or follow any of the integral types, except enum, and can also be used alone as type specifiers, in which case they are understood as signed int and unsigned int, respectively. When used alone, the keyword int is assumed to be signed. When used alone, the keywords long and short are understood as long int and short int.

Enumeration types are considered basic types. Type specifiers for enumeration types are discussed in Enumeration Declarations.

The keyword void has three uses: to specify a function return type, to specify an argument-type list for a function that takes no arguments, and to specify a pointer to an unspecified type. You can use the void type to declare functions that return no value or to declare a pointer to an unspecified type. See Arguments in Chapter 6 for information on void when it appears alone within the parentheses following a function name.

Microsoft Specific —>

Type checking is now ANSI-compliant, which means that type short and type int are distinct types. For example, this is a redefinition in the Microsoft C compiler that was accepted by previous versions of the compiler.

int   myfunc();
short myfunc();

This next example also generates a warning about indirection to different types:

int *pi;
short *ps;

ps = pi;  /* Now generates warning */

The Microsoft C compiler also generates warnings for differences in sign. For example:

signed int *pi;
unsigned int *pu

pi = pu;  /* Now generates warning */

Type void expressions are evaluated for side effects. You cannot use the (nonexistent) value of an expression that has type void in any way, nor can you convert a void expression (by implicit or explicit conversion) to any type except void. If you do use an expression of any other type in a context where a void expression is required, its value is discarded.

To conform to the ANSI specification, void** cannot be used as int**. Only void* can be used as a pointer to an unspecified type.

END Microsoft Specific

You can create additional type specifiers with typedef declarations, as described in Typedef Declarations. See Storage of Basic Types for information on the size of each type.


Data Type Specifiers and Equivalents

This book generally uses the forms of the type specifiers listed in Table 3.1 rather than the long forms, and it assumes that the char type is signed by default. Therefore, throughout this book, char is equivalent to signed char.

Table 3.1 Type Specifiers and Equivalents

Type Specifier | Equivalent(s)
signed char1 | char
signed int | signed, int
signed short int | short, signed short
signed long int | long, signed long
unsigned char | —
unsigned int | unsigned
unsigned short int | unsigned short
unsigned long int | unsigned long
float | —
long double2 | —

1 When you make the char type unsigned by default (by specifying the /J compiler option), you cannot abbreviate signed char as char.

2 In 32-bit operating systems, the Microsoft C compiler maps long double to type double.

Microsoft Specific —>

You can specify the /J compiler option to change the default char type from signed to unsigned. When this option is in effect, char means the same as unsigned char, and you must use the signed keyword to declare a signed character value. If a char value is explicitly declared signed, the /J option does not affect it, and the value is sign-extended when widened to an int type. The char type is zero-extended when widened to int type.

END Microsoft Specific


Type Qualifiers

Type qualifiers give one of two properties to an identifier. The const type qualifier declares an object to be nonmodifiable. The volatile type qualifier declares an item whose value can legitimately be changed by something beyond the control of the program in which it appears, such as a concurrently executing thread.

The two type qualifiers, const and volatile, can appear only once in a declaration. Type qualifiers can appear with any type specifier; however, they cannot appear after the first comma in a multiple item declaration. For example, the following declarations are legal:

typedef volatile int VI;
const int ci;

These declarations are not legal:

typedef int *i, volatile *vi;
float f, const cf;

Type qualifiers are relevant only when accessing identifiers as l-values in expressions. See L-Value and R-Value Expressions in Chapter 4 for information about l-values and expressions.

Syntax

type-qualifier :

const
volatile

The following are legal const and volatile declarations:

int const *p_ci;       /* Pointer to constant int */
int const (*p_ci);     /* Pointer to constant int */
int *const cp_i;       /* Constant pointer to int */
int (*const cp_i);     /* Constant pointer to int */
int volatile vint;     /* Volatile integer        */

If the specification of an array type includes type qualifiers, the element is qualified, not the array type. If the specification of the function type includes qualifiers, the behavior is undefined. Neither volatile nor const affects the range of values or arithmetic properties of the object.

This list describes how to use const and volatile.

  • The const keyword can be used to modify any fundamental or aggregate type, or a pointer to an object of any type, or a typedef. If an item is declared with only the const type qualifier, its type is taken to be const int. A const variable can be initialized or can be placed in a read-only region of storage. The const keyword is useful for declaring pointers to const since this requires the function not to change the pointer in any way.

  • The compiler assumes that, at any point in the program, a volatile variable can be accessed by an unknown process that uses or modifies its value. Therefore, regardless of the optimizations specified on the command line, the code for each assignment to or reference of a volatile variable must be generated even if it appears to have no effect.

    If volatile is used alone, int is assumed. The volatile type specifier can be used to provide reliable access to special memory locations. Use volatile with data objects that may be accessed or altered by signal handlers, by concurrently executing programs, or by special hardware such as memory-mapped I/O control registers. You can declare a variable as volatile for its lifetime, or you can cast a single reference to be volatile.

  • An item can be both const and volatile, in which case the item could not be legitimately modified by its own program, but could be modified by some asynchronous process.


Declarators and Variable Declarations

The rest of this chapter describes the form and meaning of declarations for variable types summarized in this list. In particular, the remaining sections explain how to declare the following:

Type of Variable | Description
Simple variables | Single-value variables with integral or floating-point type
Arrays | Variables composed of a collection of elements with the same type
Pointers | Variables that point to other variables and contain variable locations (in the form of addresses) instead of values
Enumeration variables | Simple variables with integral type that hold one value from a set of named integer constants
Structures | Variables composed of a collection of values that can have different types
Unions | Variables composed of several values of different types that occupy the same storage space

A declarator is the part of a declaration that specifies the name that is to be introduced into the program. It can include modifiers such as * (pointer-to) and any of the Microsoft calling-convention keywords.

Microsoft Specific —>

In the declarator

__declspec(thread) char *var;

char is the type specifier, __declspec(thread) and * are the modifiers, and var is the identifier’s name.

END Microsoft Specific

You use declarators to declare arrays of values, pointers to values, and functions returning values of a specified type. Declarators appear in the array and pointer declarations described later in this chapter.

Syntax

declarator :

pointer opt direct-declarator

direct-declarator :

identifier
( declarator )
direct-declarator [ constant-expression opt ]
direct-declarator ( parameter-type-list )
direct-declarator ( identifier-list opt )

pointer :

* type-qualifier-list opt
* type-qualifier-list opt pointer

type-qualifier-list :

type-qualifier
type-qualifier-list type-qualifier

Note See the syntax for declaration in Overview of Declarations, or see Appendix A, C Language Syntax Summary, for the syntax that references a declarator.

When a declarator consists of an unmodified identifier, the item being declared has a base type. If an asterisk (*) appears to the left of an identifier, the type is modified to a pointer type. If the identifier is followed by brackets ([ ]), the type is modified to an array type. If the identifier is followed by parentheses, the type is modified to a function type. For more information about interpreting precedence within declarations, see Interpreting More Complex Declarators.

Each declarator declares at least one identifier. A declarator must include a type specifier to be a complete declaration. The type specifier gives the type of the elements of an array type, the type of object addressed by a pointer type, or the return type of a function.

Array and pointer declarations are discussed in more detail later in this chapter. The following examples illustrate a few simple forms of declarators:

int list[20]; /* Declares an array of 20 int values named list */
char *cp;     /* Declares a pointer to a char value */
double func( void ); /* Declares a function named func, with no
                        arguments, that returns a double value */
int *aptr[10]         /* Declares an array of 10 pointers */

Microsoft Specific —>

The Microsoft C compiler does not limit the number of declarators that can modify an arithmetic, structure, or union type. The number is limited only by available memory.

END Microsoft Specific


Simple Variable Declarations

The declaration of a simple variable, the simplest form of a direct declarator, specifies the variable’s name and type. It also specifies the variable’s storage class and data type.

Storage classes or types (or both) are required on variable declarations. Untyped variables (such as var;) generate warnings.

Syntax

declarator :

pointer opt direct-declarator

direct-declarator :

identifier

identifier :

nondigit
identifier nondigit
identifier digit

For arithmetic, structure, union, enumerations, and void types, and for types represented by typedef names, simple declarators can be used in a declaration since the type specifier supplies all the typing information. Pointer, array, and function types require more complicated declarators.

You can use a list of identifiers separated by commas (,) to specify several variables in the same declaration. All variables defined in the declaration have the same base type. For example:

int x, y;        /* Declares two simple variables of type int */
int const z = 1; /* Declares a constant value of type int */

The variables x and y can hold any value in the set defined by the int type for a particular implementation. The simple object z is initialized to the value 1 and is not modifiable.

If the declaration of z was for an uninitialized static variable or was at file scope, it would receive an initial value of 0, and that value would be unmodifiable.

unsigned long reply, flag; /* Declares two variables
                              named reply and flag     */

In this example, both the variables, reply and flag, have unsigned long type and hold unsigned integral values.


C Enumeration Declarations

An enumeration consists of a set of named integer constants. An enumeration type declaration gives the name of the (optional) enumeration tag and defines the set of named integer identifiers (called the “enumeration set,” “enumerator constants,” “enumerators,” or “members”). A variable with enumeration type stores one of the values of the enumeration set defined by that type.

Variables of enum type can be used in indexing expressions and as operands of all arithmetic and relational operators. Enumerations provide an alternative to the #define preprocessor directive with the advantages that the values can be generated for you and obey normal scoping rules.

In ANSI C, the expressions that define the value of an enumerator constant always have int type; thus, the storage associated with an enumeration variable is the storage required for a single int value. An enumeration constant or a value of enumerated type can be used anywhere the C language permits an integer expression.

Syntax

enum-specifier :

enum identifier opt { enumerator-list }
enum identifier

The optional identifier names the enumeration type defined by enumerator-list. This identifier is often called the “tag” of the enumeration specified by the list. A type specifier of the form

enum identifier { enumerator-list }

declares identifier to be the tag of the enumeration specified by the enumerator-list nonterminal. The enumerator-list defines the “enumerator content.” The enumerator-list is described in detail below.

If the declaration of a tag is visible, subsequent declarations that use the tag but omit enumerator-list specify the previously declared enumerated type. The tag must refer to a defined enumeration type, and that enumeration type must be in current scope. Since the enumeration type is defined elsewhere, the enumerator-list does not appear in this declaration. Declarations of types derived from enumerations and typedef declarations for enumeration types can use the enumeration tag before the enumeration type is defined.

Syntax

enumerator-list :

enumerator
enumerator-list , enumerator

enumerator :

enumeration-constant
enumeration-constant = constant-expression

enumeration-constant :

identifier

Each enumeration-constant in an enumeration-list names a value of the enumeration set. By default, the first enumeration-constant is associated with the value 0. The next enumeration-constant in the list is associated with the value of ( constant-expression + 1 ), unless you explicitly associate it with another value. The name of an enumeration-constant is equivalent to its value.

You can use enumeration-constant = constant-expression to override the default sequence of values. Thus, if enumeration-constant = constant-expression appears in the enumerator-list, the enumeration-constant is associated with the value given by constant-expression. The constant-expression must have int type and can be negative.

The following rules apply to the members of an enumeration set:

  • An enumeration set can contain duplicate constant values. For example, you could associate the value 0 with two different identifiers, perhaps named null and zero, in the same set.

  • The identifiers in the enumeration list must be distinct from other identifiers in the same scope with the same visibility, including ordinary variable names and identifiers in other enumeration lists.

  • Enumeration tags obey the normal scoping rules. They must be distinct from other enumeration, structure, and union tags with the same visibility.

Examples

These examples illustrate enumeration declarations:

enum DAY            /* Defines an enumeration type    */
{
    saturday,       /* Names day and declares a       */
    sunday = 0,     /* variable named workday with    */
    monday,         /* that type                      */
    tuesday,
    wednesday,      /* wednesday is associated with 3 */
    thursday,
    friday
} workday;

The value 0 is associated with saturday by default. The identifier sunday is explicitly set to 0. The remaining identifiers are given the values 1 through 5 by default.

In this example, a value from the set DAY is assigned to the variable today.

enum DAY today = wednesday;

Note that the name of the enumeration constant is used to assign the value. Since the DAY enumeration type was previously declared, only the enumeration tag DAY is necessary.

To explicitly assign an integer value to a variable of an enumerated data type, use a type cast:

workday = ( enum DAY ) ( day_value - 1 );

This cast is recommended in C but is not required.

enum BOOLEAN  /* Declares an enumeration data type called BOOLEAN */
{
    false,     /* false = 0, true = 1 */
    true
};

enum BOOLEAN end_flag, match_flag; /* Two variables of type BOOLEAN */

This declaration can also be specified as

enum BOOLEAN { false, true } end_flag, match_flag;\

or as

enum BOOLEAN { false, true } end_flag;
enum BOOLEAN match_flag;

An example that uses these variables might look like this:

if ( match_flag == false )
    {
     .
     .   /* statement */
     .
    }
    end_flag = true;

Unnamed enumerator data types can also be declared. The name of the data type is omitted, but variables can be declared. The variable response is a variable of the type defined:

enum { yes, no } response;


Structure Declarations

A “structure declaration” names a type and specifies a sequence of variable values (called “members” or “fields” of the structure) that can have different types. An optional identifier, called a “tag,” gives the name of the structure type and can be used in subsequent references to the structure type. A variable of that structure type holds the entire sequence defined by that type. Structures in C are similar to the types known as “records” in other languages.

Syntax

struct-or-union-specifier :

struct-or-union identifier opt { struct-declaration-list }
struct-or-union identifier

struct-or-union :

struct
union

struct-declaration-list :

struct-declaration
struct-declaration-list struct-declaration

The structure content is defined to be

struct-declaration :

specifier-qualifier-list struct-declarator-list ;

specifier-qualifier-list :

type-specifier specifier-qualifier-list opt
type-qualifier specifier-qualifier-list opt

struct-declarator-list :

struct-declarator
struct-declarator-list , struct-declarator

struct-declarator :

declarator

The declaration of a structure type does not set aside space for a structure. It is only a template for later declarations of structure variables.

A previously defined identifier (tag) can be used to refer to a structure type defined elsewhere. In this case, struct-declaration-list cannot be repeated as long as the definition is visible. Declarations of pointers to structures and typedefs for structure types can use the structure tag before the structure type is defined. However, the structure definition must be encountered prior to any actual use of the size of the fields. This is an incomplete definition of the type and the type tag. For this definition to be completed, a type definition must appear later in the same scope.

The struct-declaration-list specifies the types and names of the structure members. A struct-declaration-list argument contains one or more variable or bit-field declarations.

Each variable declared in struct-declaration-list is defined as a member of the structure type. Variable declarations within struct-declaration-list have the same form as other variable declarations discussed in this chapter, except that the declarations cannot contain storage-class specifiers or initializers. The structure members can have any variable types except type void, an incomplete type, or a function type.

A member cannot be declared to have the type of the structure in which it appears. However, a member can be declared as a pointer to the structure type in which it appears as long as the structure type has a tag. This allows you to create linked lists of structures.

Structures follow the same scoping as other identifiers. Structure identifiers must be distinct from other structure, union, and enumeration tags with the same visibility.

Each struct-declaration in a struct-declaration-list must be unique within the list. However, identifier names in a struct-declaration-list do not have to be distinct from ordinary variable names or from identifiers in other structure declaration lists.

Nested structures can also be accessed as though they were declared at the file-scope level. For example, given this declaration:

struct a
{
    int x;
    struct b
    {
      int y;
    } var2;
} var1;

these declarations are both legal:

struct a var3;
struct b var4;

Examples

These examples illustrate structure declarations:

struct employee   /* Defines a structure variable named temp */
{
    char name[20];
    int id;
    long class;
} temp;

The employee structure has three members: name, id, and class. The name member is a 20-element array, and id and class are simple members with int and long type, respectively. The identifier employee is the structure identifier.

struct employee student, faculty, staff;

This example defines three structure variables: student, faculty, and staff. Each structure has the same list of three members. The members are declared to have the structure type employee, defined in the previous example.

struct           /* Defines an anonymous struct and a */
{                /* structure variable named complex  */
    float x, y;
} complex;

The complex structure has two members with float type, x and y. The structure type has no tag and is therefore unnamed or anonymous.

struct sample   /* Defines a structure named x */
{
    char c;
    float *pf;
    struct sample *next;
} x;

The first two members of the structure are a char variable and a pointer to a float value. The third member, next, is declared as a pointer to the structure type being defined (sample).

Anonymous structures can be useful when the tag named is not needed. This is the case when one declaration defines all structure instances. For example:

struct
{
    int x;
    int y;
} mystruct;

Embedded structures are often anonymous.

struct somestruct
{
    struct    /* Anonymous structure */
    {
        int x, y;
    } point;
    int type;
} w;

Microsoft Specific —>

The compiler allows an unsized or zero-sized array as the last member of a structure. This can be useful if the size of a constant array differs when used in various situations. The declaration of such a structure looks like this:

struct identifier
{
set-of-declarations
type array-name[ ];
};

Unsized arrays can appear only as the last member of a structure. Structures containing unsized array declarations can be nested within other structures as long as no further members are declared in any enclosing structures. Arrays of such structures are not allowed. The sizeof operator, when applied to a variable of this type or to the type itself, assumes 0 for the size of the array.

Structure declarations can also be specified without a declarator when they are members of another structure or union. The field names are promoted into the enclosing structure. For example, a nameless structure looks like this:

struct s
{
    float y;
    struct
    {
        int a, b, c;
    };
    char str[10];
} *p_s;
.
.
.
p_s->b = 100;  /* A reference to a field in the s structure */

See Structure and Union Members for information about structure references.

END Microsoft Specific


C Bit Fields

In addition to declarators for members of a structure or union, a structure declarator can also be a specified number of bits, called a “bit field.” Its length is set off from the declarator for the field name by a colon. A bit field is interpreted as an integral type.

Syntax

struct-declarator :

declarator
type-specifier declarator opt : constant-expression

The constant-expression specifies the width of the field in bits. The type-specifier for the declarator must be unsigned int, signed int, or int, and the constant-expression must be a nonnegative integer value. If the value is zero, the declaration has no declarator. Arrays of bit fields, pointers to bit fields, and functions returning bit fields are not allowed. The optional declarator names the bit field. Bit fields can only be declared as part of a structure. The address-of operator (&) cannot be applied to bit-field components.

Unnamed bit fields cannot be referenced, and their contents at run time are unpredictable. They can be used as “dummy” fields, for alignment purposes. An unnamed bit field whose width is specified as 0 guarantees that storage for the member following it in the struct-declaration-list begins on an int boundary.

Bit fields must also be long enough to contain the bit pattern. For example, these two statements are not legal:

short a:17;        /* Illegal! */
int long y:33;     /* Illegal! */

This example defines a two-dimensional array of structures named screen.

struct
{
    unsigned short icon : 8;
    unsigned short color : 4;
    unsigned short underline : 1;
    unsigned short blink : 1;
} screen[25][80];

The array contains 2,000 elements. Each element is an individual structure containing four bit-field members: icon, color, underline, and blink. The size of each structure is two bytes.

Bit fields have the same semantics as the integer type. This means a bit field is used in expressions in exactly the same way as a variable of the same base type would be used, regardless of how many bits are in the bit field.

Microsoft Specific —>

Bit fields defined as int are treated as signed. A Microsoft extension to the ANSI C standard allows char and long types (both signed and unsigned) for bit fields. Unnamed bit fields with base type long, short, or char (signed or unsigned) force alignment to a boundary appropriate to the base type.

Bit fields are allocated within an integer from least-significant to most-significant bit. In the following code

struct mybitfields
{
    unsigned short a : 4;
    unsigned short b : 5;
    unsigned short c : 7;
} test;

void main( void );
{
    test.a = 2;
    test.b = 31;
    test.c = 0;
}

the bits would be arranged as follows:

00000001 11110010
cccccccb bbbbaaaa

Since the 8086 family of processors stores the low byte of integer values before the high byte, the integer 0x01F2 above would be stored in physical memory as 0xF2 followed by 0x01.

END Microsoft Specific


Storage and Alignment of Structures

Microsoft Specific —>

Structure members are stored sequentially in the order in which they are declared: the first member has the lowest memory address and the last member the highest.

Every data object has an alignment-requirement. For structures, the requirement is the largest of its members. Every object is allocated an offset so that

offset % alignment-requirement == 0

Adjacent bit fields are packed into the same 1-, 2-, or 4-byte allocation unit if the integral types are the same size and if the next bit field fits into the current allocation unit without crossing the boundary imposed by the common alignment requirements of the bit fields.

To conserve space or to conform to existing data structures, you may want to store structures more or less compactly. The /Zp[n] compiler option and the #pragma pack control how structure data is “packed” into memory. When you use the /Zp[n] option, where n is 1, 2, 4, 8, or 16, each structure member after the first is stored on byte boundaries that are either the alignment requirement of the field or the packing size (n), whichever is smaller. Expressed as a formula, the byte boundaries are the

min( n, sizeof( item ) )

where n is the packing size expressed with the /Zp[n] option and item is the structure member. The default packing size is /Zp8.

To use the pack pragma to specify packing other than the packing specified on the command line for a particular structure, give the pack pragma, where the packing size is 1, 2, 4, 8, or 16, before the structure. To reinstate the packing given on the command line, specify the pack pragma with no arguments.

Bit fields default to size long for the Microsoft C compiler. Structure members are aligned on the size of the type or the /Zp[n] size, whichever is smaller. The default size is 4.

END Microsoft Specific


Union Declarations

A “union declaration” specifies a set of variable values and, optionally, a tag naming the union. The variable values are called “members” of the union and can have different types. Unions are similar to “variant records” in other languages.

Syntax

struct-or-union-specifier :

struct-or-union identifier opt { struct-declaration-list }
struct-or-union identifier

struct-or-union :

struct
union

struct-declaration-list :

struct-declaration
struct-declaration-list struct-declaration

The union content is defined to be

struct-declaration :

specifier-qualifier-list struct-declarator-list ;

specifier-qualifier-list :

type-specifier specifier-qualifier-list opt
type-qualifier specifier-qualifier-list opt

struct-declarator-list :

struct-declarator
struct-declarator-list , struct-declarator

A variable with union type stores one of the values defined by that type. The same rules govern structure and union declarations. Unions can also have bit fields.

Members of unions cannot have an incomplete type, type void, or function type. Therefore members cannot be an instance of the union but can be pointers to the union type being declared.

A union type declaration is a template only. Memory is not reserved until the variable is declared.

Note If a union of two types is declared and one value is stored, but the union is accessed with the other type, the results are unreliable. For example, a union of float and int is declared. A float value is stored, but the program later accesses the value as an int. In such a situation, the value would depend on the internal storage of float values. The integer value would not be reliable.

Examples

The following are examples of unions:

union sign   /* A definition and a declaration */
{
    int svar;
    unsigned uvar;
} number;

This example defines a union variable with sign type and declares a variable named number that has two members: svar, a signed integer, and uvar, an unsigned integer. This declaration allows the current value of number to be stored as either a signed or an unsigned value. The tag associated with this union type is sign.

union               /* Defines a two-dimensional */
{                   /*  array named screen */
    struct
    {
      unsigned int icon : 8;
      unsigned color : 4;
    } window1;
    int screenval;
} screen[25][80];

The screen array contains 2,000 elements. Each element of the array is an individual union with two members: window1 and screenval. The window1 member is a structure with two bit-field members, icon and color. The screenval member is an int. At any given time, each union element holds either the int represented by screenval or the structure represented by window1.

Microsoft Specific —>

Nested unions can be declared anonymously when they are members of another structure or union. This is an example of a nameless union:

struct str
{
    int a, b;
    union            / * Unnamed union */
    {
      char c[4];
      long l;
      float f;
   };
   char c_array[10];
} my_str;
.
.
.
my_str.l == 0L;  /* A reference to a field in the my_str union */

Unions are often nested within a structure that includes a field giving the type of data contained in the union at any particular time. This is an example of a declaration for such a union:

struct x
{
    int type_tag;
    union
    {
      int x;
      float y;
    }
}

See Structure and Union Members for information about referencing unions.

END Microsoft Specific


Storage of Unions

The storage associated with a union variable is the storage required for the largest member of the union. When a smaller member is stored, the union variable can contain unused memory space. All members are stored in the same memory space and start at the same address. The stored value is overwritten each time a value is assigned to a different member. For example:

union         /* Defines a union named x */
{
    char *a, b;
    float f[20];
} x;

The members of the x union are, in order of their declaration, a pointer to a char value, a char value, and an array of float values. The storage allocated for x is the storage required for the 20-element array f, since f is the longest member of the union. Because no tag is associated with the union, its type is unnamed or “anonymous.”


Array Declarations

An “array declaration” names the array and specifies the type of its elements. It can also define the number of elements in the array. A variable with array type is considered a pointer to the type of the array elements.

Syntax

declaration :

declaration-specifiers init-declarator-list opt ;

init-declarator-list :

init-declarator
init-declarator-list , init-declarator

init-declarator :

declarator
declarator = initializer

declarator :

pointer opt direct-declarator

direct-declarator :

direct-declarator [ constant-expression opt ]

Because constant-expression is optional, the syntax has two forms:

  • The first form defines an array variable. The constant-expression argument within the brackets specifies the number of elements in the array. The constant-expression, if present, must have integral type, and a value larger than zero. Each element has the type given by type-specifier, which can be any type except void. An array element cannot be a function type.

  • The second form declares a variable that has been defined elsewhere. It omits the constant-expression argument in brackets, but not the brackets. You can use this form only if you previously have initialized the array, declared it as a parameter, or declared it as a reference to an array explicitly defined elsewhere in the program.

In both forms, direct-declarator names the variable and can modify the variable’s type. The brackets ([ ]) following direct-declarator modify the declarator to an array type.

Type qualifiers can appear in the declaration of an object of array type, but the qualifiers apply to the elements rather than the array itself.

You can declare an array of arrays (a “multidimensional” array) by following the array declarator with a list of bracketed constant expressions in this form:

type-specifier declarator [constant-expression] [constant-expression] ...

Each constant-expression in brackets defines the number of elements in a given dimension: two-dimensional arrays have two bracketed expressions, three-dimensional arrays have three, and so on. You can omit the first constant expression if you have initialized the array, declared it as a parameter, or declared it as a reference to an array explicitly defined elsewhere in the program.

You can define arrays of pointers to various types of objects by using complex declarators, as described in Interpreting More Complex Declarators.

Arrays are stored by row. For example, the following array consists of two rows with three columns each:

char A[2][3];

The three columns of the first row are stored first, followed by the three columns of the second row. This means that the last subscript varies most quickly.

To refer to an individual element of an array, use a subscript expression, as described in Postfix Operators in Chapter 4.

Examples

These examples illustrate array declarations:

float matrix[10][15];

The two-dimensional array named matrix has 150 elements, each having float type.

struct {
    float x, y;
} complex[100];

This is a declaration of an array of structures. This array has 100 elements; each element is a structure containing two members.

extern char *name[];

This statement declares the type and name of an array of pointers to char. The actual definition of name occurs elsewhere.

Microsoft Specific —>

The type of integer required to hold the maximum size of an array is the size of size_t. Defined in the header file STDDEF.H, size_t is an unsigned int with the range 0x00000000 to 0x7CFFFFFF.

END Microsoft Specific


Storage of Arrays

The storage associated with an array type is the storage required for all of its elements. The elements of an array are stored in contiguous and increasing memory locations, from the first element to the last.


Pointer Declarations

A “pointer declaration” names a pointer variable and specifies the type of the object to which the variable points. A variable declared as a pointer holds a memory address.

Syntax

declarator :

pointer opt direct-declarator

direct-declarator :

identifier
( declarator )
direct-declarator [ constant-expression opt ]
direct-declarator ( parameter-type-list )
direct-declarator ( identifier-list opt )

pointer :

* type-qualifier-list opt
* type-qualifier-list opt pointer

type-qualifier-list :

type-qualifier
type-qualifier-list type-qualifier

The type-specifier gives the type of the object, which can be any basic, structure, or union type. Pointer variables can also point to functions, arrays, and other pointers. (For information on declaring and interpreting more complex pointer types, refer to Interpreting More Complex Declarators.)

By making the type-specifier void, you can delay specification of the type to which the pointer refers. Such an item is referred to as a “pointer to void” and is written as void *. A variable declared as a pointer to void can be used to point to an object of any type. However, to perform most operations on the pointer or on the object to which it points, the type to which it points must be explicitly specified for each operation. (Variables of type char * and type void * are assignment-compatible without a type cast.) Such conversion can be accomplished with a type cast (see Type-Cast Conversions for more information).

The type-qualifier can be either const or volatile, or both. These specify, respectively, that the pointer cannot be modified by the program itself (const), or that the pointer can legitimately be modified by some process beyond the control of the program (volatile). (See Type Qualifiers for more information on const and volatile.)

The declarator names the variable and can include a type modifier. For example, if declarator represents an array, the type of the pointer is modified to be a pointer to an array.

You can declare a pointer to a structure, union, or enumeration type before you define the structure, union, or enumeration type. You declare the pointer by using the structure or union tag as shown in the examples below. Such declarations are allowed because the compiler does not need to know the size of the structure or union to allocate space for the pointer variable.

Examples

The following examples illustrate pointer declarations.

char *message; /* Declares a pointer variable named message */

The message pointer points to a variable with char type.

int *pointers[10];  /* Declares an array of pointers */

The pointers array has 10 elements; each element is a pointer to a variable with int type.

int (*pointer)[10]; /* Declares a pointer to an array of 10 elements */

The pointer variable points to an array with 10 elements. Each element in this array has int type.

int const *x;      /* Declares a pointer variable, x,
                      to a constant value */

The pointer x can be modified to point to a different int value, but the value to which it points cannot be modified.

const int some_object = 5 ;
int other_object = 37;
int *const y = &fixed_object;
const volatile *const z = &some_object;
int *const volatile w = &some_object;

The variable y in these declarations is declared as a constant pointer to an int value. The value it points to can be modified, but the pointer itself must always point to the same location: the address of fixed_object. Similarly, z is a constant pointer, but it is also declared to point to an int whose value cannot be modified by the program. The additional specifier volatile indicates that although the value of the const int pointed to by z cannot be modified by the program, it could legitimately be modified by a process running concurrently with the program. The declaration of w specifies that the program cannot change the value pointed to and that the program cannot modify the pointer.

struct list *next, *previous; /* Uses the tag for list */

This example declares two pointer variables, next and previous, that point to the structure type list. This declaration can appear before the definition of the list structure type (see the next example), as long as the list type definition has the same visibility as the declaration.

struct list
{
    char *token;
    int count;
    struct list *next;
} line;

The variable line has the structure type named list. The list structure type has three members: the first member is a pointer to a char value, the second is an int value, and the third is a pointer to another list structure.

struct id
{
    unsigned int id_no;
    struct name *pname;
} record;

The variable record has the structure type id. Note that pname is declared as a pointer to another structure type named name. This declaration can appear before the name type is defined.


Storage of Addresses

The amount of storage required for an address and the meaning of the address depend on the implementation of the compiler. Pointers to different types are not guaranteed to have the same length. Therefore, sizeof(char *) is not necessarily equal to sizeof(int *).

Microsoft Specific —>

For the Microsoft C compiler, sizeof(char *) is equal to sizeof(int *).

END Microsoft Specific


Based Pointers

Microsoft Specific —>

For the Microsoft 32-bit C compiler, a based pointer is a 32-bit offset from a 32-bit pointer base. Based addressing is useful for exercising control over sections where objects are allocated, thereby decreasing the size of the executable file and increasing execution speed. In general, the form for specifying a based pointer is

type __based( base ) declarator

The “based on pointer” variant of based addressing enables specification of a pointer as a base. The based pointer, then, is an offset into the memory section starting at the beginning of the pointer on which it is based. Pointers based on pointer addresses are the only form of the __based keyword valid in 32-bit compilations. In such compilations, they are 32-bit displacements from a 32-bit base.

One use for pointers based on pointers is for persistent identifiers that contain pointers. A linked list that consists of pointers based on a pointer can be saved to disk, then reloaded to another place in memory, with the pointers remaining valid.

The following example shows a pointer based on a pointer.

void *vpBuffer;

struct llist_t
{
    void __based( vpBuffer ) *vpData;
    struct llist_t __based( vpBuffer ) *llNext;
};

The pointer vpBuffer is assigned the address of memory allocated at some later point in the program. The linked list is relocated relative to the value of vpBuffer.

END Microsoft Specific


C Abstract Declarators

An abstract declarator is a declarator without an identifier, consisting of one or more pointer, array, or function modifiers. The pointer modifier (*) always precedes the identifier in a declarator; array ([ ]) and function ( ( ) ) modifiers follow the identifier. Knowing this, you can determine where the identifier would appear in an abstract declarator and interpret the declarator accordingly. See Interpreting More Complex Declarators for additional information and examples of complex declarators. Generally typedef can be used to simplify declarators. See Typedef Declarations.

Abstract declarators can be complex. Parentheses in a complex abstract declarator specify a particular interpretation, just as they do for the complex declarators in declarations.

These examples illustrate abstract declarators:

int *         /* The type name for a pointer to type int:   */

int *[3]      /* An array of three pointers to int          */

int (*) [5]   /* A pointer to an array of five int          */

int *()       /* A function with no parameter specification */
              /* returning a pointer to int                 */

/* A pointer to a function taking no arguments and
 * returning an int
 */

int (*) ( void )

/* An array of an unspecified number of constant pointers to
 * functions each with one parameter that has type unsigned int
 * and an unspecified number of other parameters returning an int
 */

int (*const []) ( unsigned int, ... )

Note The abstract declarator consisting of a set of empty parentheses, ( ), is not allowed because it is ambiguous. It is impossible to determine whether the implied identifier belongs inside the parentheses (in which case it is an unmodified type) or before the parentheses (in which case it is a function type).


Interpreting More Complex Declarators

You can enclose any declarator in parentheses to specify a particular interpretation of a “complex declarator.” A complex declarator is an identifier qualified by more than one array, pointer, or function modifier. You can apply various combinations of array, pointer, and function modifiers to a single identifier. Generally typedef may be used to simplify declarations. See Typedef Declarations.

In interpreting complex declarators, brackets and parentheses (that is, modifiers to the right of the identifier) take precedence over asterisks (that is, modifiers to the left of the identifier). Brackets and parentheses have the same precedence and associate from left to right. After the declarator has been fully interpreted, the type specifier is applied as the last step. By using parentheses you can override the default association order and force a particular interpretation. Never use parentheses, however, around an identifier name by itself. This could be misinterpreted as a parameter list.

A simple way to interpret complex declarators is to read them “from the inside out,” using the following four steps:

  1. Start with the identifier and look directly to the right for brackets or parentheses (if any).

  2. Interpret these brackets or parentheses, then look to the left for asterisks.

  3. If you encounter a right parenthesis at any stage, go back and apply rules 1 and 2 to everything within the parentheses.

  4. Apply the type specifier.
char *( *(*var)() )[10];
 ^   ^  ^ ^ ^   ^    ^
 7   6  4 2 1   3    5

In this example, the steps are numbered in order and can be interpreted as follows:

  1. The identifier var is declared as

  2. a pointer to

  3. a function returning

  4. a pointer to

  5. an array of 10 elements, which are

  6. pointers to

  7. char values.

Examples

The following examples illustrate other complex declarations and show how parentheses can affect the meaning of a declaration.

int *var[5]; /* Array of pointers to int values */

The array modifier has higher priority than the pointer modifier, so var is declared to be an array. The pointer modifier applies to the type of the array elements; therefore, the array elements are pointers to int values.

int (*var)[5]; /* Pointer to array of int values */

In this declaration for var, parentheses give the pointer modifier higher priority than the array modifier, and var is declared to be a pointer to an array of five int values.

long *var( long, long ); /* Function returning pointer to long */

Function modifiers also have higher priority than pointer modifiers, so this declaration for var declares var to be a function returning a pointer to a long value. The function is declared to take two long values as arguments.

long (*var)( long, long ); /* Pointer to function returning long */

This example is similar to the previous one. Parentheses give the pointer modifier higher priority than the function modifier, and var is declared to be a pointer to a function that returns a long value. Again, the function takes two long arguments.

struct both       /* Array of pointers to functions */
{                 /*   returning structures         */
    int a;
    char b;
} ( *var[5] )( struct both, struct both );

The elements of an array cannot be functions, but this declaration demonstrates how to declare an array of pointers to functions instead. In this example, var is declared to be an array of five pointers to functions that return structures with two members. The arguments to the functions are declared to be two structures with the same structure type, both. Note that the parentheses surrounding *var[5] are required. Without them, the declaration is an illegal attempt to declare an array of functions, as shown below:

/* ILLEGAL */
struct both *var[5]( struct both, struct both );

The following statement declares an array of pointers.

unsigned int *(* const *name[5][10] ) ( void );

The name array has 50 elements organized in a multidimensional array. The elements are pointers to a pointer that is a constant. This constant pointer points to a function that has no parameters and returns a pointer to an unsigned type.

This next example is a function returning a pointer to an array of three double values.

double ( *var( double (*)[3] ) )[3];

In this declaration, a function returns a pointer to an array, since functions returning arrays are illegal. Here var is declared to be a function returning a pointer to an array of three double values. The function var takes one argument. The argument, like the return value, is a pointer to an array of three double values. The argument type is given by a complex abstract-declarator. The parentheses around the asterisk in the argument type are required; without them, the argument type would be an array of three pointers to double values. For a discussion and examples of abstract declarators, see Abstract Declarators.

union sign         /* Array of arrays of pointers */
{                  /* to pointers to unions       */
     int x;
     unsigned y;
} **var[5][5];

As the above example shows, a pointer can point to another pointer, and an array can contain arrays as elements. Here var is an array of five elements. Each element is a five-element array of pointers to pointers to unions with two members.

union sign *(*var[5])[5]; /* Array of pointers to arrays
                             of pointers to unions        */

This example shows how the placement of parentheses changes the meaning of the declaration. In this example, var is a five-element array of pointers to five-element arrays of pointers to unions. For examples of how to use typedef to avoid complex declarations, see Typedef Declarations.


Initialization

An “initializer” is a value or a sequence of values to be assigned to the variable being declared. You can set a variable to an initial value by applying an initializer to the declarator in the variable declaration. The value or values of the initializer are assigned to the variable.

The following sections describe how to initialize variables of scalar, aggregate, and string types. “Scalar types” include all the arithmetic types, plus pointers. “Aggregate types” include arrays, structures, and unions.


Initializing Scalar Types

When initializing scalar types, the value of the assignment-expression is assigned to the variable. The conversion rules for assignment apply. (See Type Conversions in Chapter 4 for information on conversion rules.)

Syntax

declaration :

declaration-specifiers init-declarator-list opt ;

declaration-specifiers :

storage-class-specifier declaration-specifiers opt
type-specifier declaration-specifiers opt
type-qualifier declaration-specifiers opt

init-declarator-list :

init-declarator
init-declarator-list , init-declarator

init-declarator :

declarator
declarator = initializer /* For scalar initialization */

initializer :

assignment-expression

You can initialize variables of any type, provided that you obey the following rules:

  • Variables declared at the file-scope level can be initialized. If you do not explicitly initialize a variable at the external level, it is initialized to 0 by default.

  • A constant expression can be used to initialize any global variable declared with the static storage-class-specifier. Variables declared to be static are initialized when program execution begins. If you do not explicitly initialize a global static variable, it is initialized to 0 by default, and every member that has pointer type is assigned a null pointer.

  • Variables declared with the auto or register storage-class specifier are initialized each time execution control passes to the block in which they are declared. If you omit an initializer from the declaration of an auto or register variable, the initial value of the variable is undefined. For automatic and register values, the initializer is not restricted to being a constant; it can be any expression involving previously defined values, even function calls.

  • The initial values for external variable declarations and for all static variables, whether external or internal, must be constant expressions. (For more information, see Constant Expressions in Chapter 4.) Since the address of any externally declared or static variable is constant, it can be used to initialize an internally declared static pointer variable. However, the address of an auto variable cannot be used as a static initializer because it may be different for each execution of the block. You can use either constant or variable values to initialize auto and register variables.

  • If the declaration of an identifier has block scope, and the identifier has external linkage, the declaration cannot have an initialization.

Examples

The following examples illustrate initializations:

int x = 10;

The integer variable x is initialized to the constant expression 10.

register int *px = 0;

The pointer px is initialized to 0, producing a “null” pointer.

const int c = (3 * 1024);

This example uses a constant expression (3 * 1024) to initialize c to a constant value that cannot be modified because of the const keyword.

int *b = &x;

This statement initializes the pointer b with the address of another variable, x.

int *const a = &z;

The pointer a is initialized with the address of a variable named z. However, since it is specified to be a const, the variable a can only be initialized, never modified. It always points to the same location.

int GLOBAL ;

int function( void )
{
    int LOCAL ;
    static int *lp = &LOCAL;   /* Illegal initialization */
    static int *gp = &GLOBAL;  /* Legal initialization   */
    register int *rp = &LOCAL; /* Legal initialization   */
}

The global variable GLOBAL is declared at the external level, so it has global lifetime. The local variable LOCAL has auto storage class and only has an address during the execution of the function in which it is declared. Therefore, attempting to initialize the static pointer variable lp with the address of LOCAL is not permitted. The static pointer variable gp can be initialized to the address of GLOBAL because that address is always the same. Similarly, *rp can be initialized because rp is a local variable and can have a nonconstant initializer. Each time the block is entered, LOCAL has a new address, which is then assigned to rp.


Initializing Aggregate Types

An “aggregate” type is a structure, union, or array type. If an aggregate type contains members of aggregate types, the initialization rules apply recursively.

Syntax

initializer :

{ initializer-list } /* For aggregate initialization */
{ initializer-list , }

initializer-list :

initializer
initializer-list , initializer

The initializer-list is a list of initializers separated by commas. Each initializer in the list is either a constant expression or an initializer list. Therefore, initializer lists can be nested. This form is useful for initializing aggregate members of an aggregate type, as shown in the examples in this section. However, if the initializer for an automatic identifier is a single expression, it need not be a constant expression; it merely needs to have appropriate type for assignment to the identifier.

For each initializer list, the values of the constant expressions are assigned, in order, to the corresponding members of the aggregate variable.

If initializer-list has fewer values than an aggregate type, the remaining members or elements of the aggregate type are initialized to 0 for external and static variables. The initial value of an automatic identifier not explicitly initialized is undefined. If initializer-list has more values than an aggregate type, an error results. These rules apply to each embedded initializer list, as well as to the aggregate as a whole.

A structure’s initializer is either an expression of the same type, or a list of initializers for its members enclosed in curly braces ({ }). Unnamed bit-field members are not initialized.

When a union is initialized, initializer-list must be a single constant expression. The value of the constant expression is assigned to the first member of the union.

If an array has unknown size, the number of initializers determines the size of the array, and its type becomes complete. There is no way to specify repetition of an initializer in C, or to initialize an element in the middle of an array without providing all preceding values as well. If you need this operation in your program, write the routine in assembly language.

Note that the number of initializers can set the size of the array:

int x[ ] = { 0, 1, 2 }

If you specify the size and give the wrong number of initializers, however, the compiler generates an error.

Microsoft Specific —>

The maximum size for an array is defined by size_t. Defined in the header file STDDEF.H, size_t is an unsigned int with the range 0x00000000 to 0x7CFFFFFF.

END Microsoft Specific

Examples

This example shows initializers for an array.

int P[4][3] =
{
    { 1, 1, 1 },
    { 2, 2, 2 },
    { 3, 3, 3,},
    { 4, 4, 4,},
};

This statement declares P as a four-by-three array and initializes the elements of its first row to 1, the elements of its second row to 2, and so on through the fourth row. Note that the initializer list for the third and fourth rows contains commas after the last constant expression. The last initializer list ({4, 4, 4,},) is also followed by a comma. These extra commas are permitted but are not required; only commas that separate constant expressions from one another, and those that separate one initializer list from another, are required.

If an aggregate member has no embedded initializer list, values are simply assigned, in order, to each member of the subaggregate. Therefore, the initialization in the previous example is equivalent to the following:

int P[4][3] =
{
   1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4
};

Braces can also appear around individual initializers in the list and would help to clarify the example above.

When you initialize an aggregate variable, you must be careful to use braces and initializer lists properly. The following example illustrates the compiler’s interpretation of braces in more detail:

typedef struct
{
    int n1, n2, n3;
} triplet;

triplet nlist[2][3] =
{
    { {  1, 2, 3 }, {  4, 5, 6 }, {  7, 8, 9 } },  /* Row 1 */
    { { 10,11,12 }, { 13,14,15 }, { 16,17,18 } }   /* Row 2 */
};

In this example, nlist is declared as a 2-by-3 array of structures, each structure having three members. Row 1 of the initialization assigns values to the first row of nlist, as follows:

  1. The first left brace on row 1 signals the compiler that initialization of the first aggregate member of nlist (that is, nlist[0]) is beginning.

  2. The second left brace indicates that initialization of the first aggregate member of nlist[0] (that is, the structure at nlist[0][0]) is beginning.

  3. The first right brace ends initialization of the structure nlist[0][0]; the next left brace starts initialization of nlist[0][1].

  4. The process continues until the end of the line, where the closing right brace ends initialization of nlist[0].

Row 2 assigns values to the second row of nlist in a similar way. Note that the outer sets of braces enclosing the initializers on rows 1 and 2 are required. The following construction, which omits the outer braces, would cause an error:

triplet nlist[2][3] =  /* THIS CAUSES AN ERROR */
{
     {  1, 2, 3 },{  4, 5, 6 },{  7, 8, 9 },   /* Line 1 */
     { 10,11,12 },{ 13,14,15 },{ 16,17,18 }    /* Line 2 */
};

In this construction, the first left brace on line 1 starts the initialization of nlist[0], which is an array of three structures. The values 1, 2, and 3 are assigned to the three members of the first structure. When the next right brace is encountered (after the value 3), initialization of nlist[0] is complete, and the two remaining structures in the three-structure array are automatically initialized to 0. Similarly, { 4,5,6 } initializes the first structure in the second row of nlist. The remaining two structures of nlist[1] are set to 0. When the compiler encounters the next initializer list ( { 7,8,9 } ), it tries to initialize nlist[2]. Since nlist has only two rows, this attempt causes an error.

In this next example, the three int members of x are initialized to 1, 2, and 3, respectively.

struct list
{
    int i, j, k;
    float m[2][3];
} x = {
        1,
        2,
        3,
       {4.0, 4.0, 4.0}
      };

In the list structure above, the three elements in the first row of m are initialized to 4.0; the elements of the remaining row of m are initialized to 0.0 by default.

union
{
    char x[2][3];
    int i, j, k;
} y = { {
            {'1'},
            {'4'}
        }
      };

The union variable y, in this example, is initialized. The first element of the union is an array, so the initializer is an aggregate initializer. The initializer list {'1'} assigns values to the first row of the array. Since only one value appears in the list, the element in the first column is initialized to the character 1, and the remaining two elements in the row are initialized to the value 0 by default. Similarly, the first element of the second row of x is initialized to the character 4, and the remaining two elements in the row are initialized to the value 0.


Initializing Strings

You can initialize an array of characters (or wide characters) with a string literal (or wide string literal). For example:

char code[ ] = "abc";

initializes code as a four-element array of characters. The fourth element is the null character, which terminates all string literals.

An identifier list can only be as long as the number of identifiers to be initialized. If you specify an array size that is shorter than the string, the extra characters are ignored. For example, the following declaration initializes code as a three-element character array:

char code[3] = "abcd";

Only the first three characters of the initializer are assigned to code. The character d and the string-terminating null character are discarded. Note that this creates an unterminated string (that is, one without a 0 value to mark its end) and generates a diagnostic message indicating this condition.

The declaration

char s[] = "abc", t[3] = "abc";

is identical to

char s[]  = {'a', 'b', 'c', '\0'},
     t[3] = {'a', 'b', 'c' };

If the string is shorter than the specified array size, the remaining elements of the array are initialized to 0.

Microsoft Specific —>

In Microsoft C, string literals can be up to 2048 bytes in length.

END Microsoft Specific


Storage of Basic Types

Table 3.2 summarizes the storage associated with each basic type.

Table 3.2 Sizes of Fundamental Types

Type | Storage
char, unsigned char, signed char | 1 byte
short, unsigned short | 2 bytes
int, unsigned int | 4 bytes
long, unsigned long | 4 bytes
float | 4 bytes
double | 8 bytes
long double | 8 bytes

The C data types fall into general categories. The “integral types” include char, int, short, long, signed, unsigned, and enum. The “floating types” include float, double, and long double. The “arithmetic types” include all floating and integral types.


Type char

The char type is used to store the integer value of a member of the representable character set. That integer value is the ASCII code corresponding to the specified character.

Microsoft Specific —>

Character values of type unsigned char have a range from 0 to 0xFF hexadecimal. A signed char has range 0x80 to 0x7F. These ranges translate to 0 to 255 decimal, and –128 to +127 decimal, respectively. The /J compiler option changes the default from signed to unsigned.

END Microsoft Specific


Type int

The size of a signed or unsigned int item is the standard size of an integer on a particular machine. For example, in 16-bit operating systems, the int type is usually 16 bits, or 2 bytes. In 32-bit operating systems, the int type is usually 32 bits, or 4 bytes. Thus, the int type is equivalent to either the short int or the long int type, and the unsigned int type is equivalent to either the unsigned short or the unsigned long type, depending on the target environment. The int types all represent signed values unless specified otherwise.

The type specifiers int and unsigned int (or simply unsigned) define certain features of the C language (for instance, the enum type). In these cases, the definitions of int and unsigned int for a particular implementation determine the actual storage.

Microsoft Specific —>

Signed integers are represented in two’s-complement form. The most-significant bit holds the sign: 1 for negative, 0 for positive and zero. The range of values is given in Table 1.3, which is taken from the LIMITS.H header file.

END Microsoft Specific

Note The int and unsigned int type specifiers are widely used in C programs because they allow a particular machine to handle integer values in the most efficient way for that machine. However, since the sizes of the int and unsigned int types vary, programs that depend on a specific int size may not be portable to other machines. To make programs more portable, you can use expressions with the sizeof operator (as discussed in The sizeof Operator in Chapter 4) instead of hard-coded data sizes.


C Sized Integer Types

Microsoft Specific —>

Microsoft C features support for sized integer types. You can declare 8-, 16-, 32-, or 64-bit integer variables by using the __intn type specifier, where n is the size, in bits, of the integer variable. The value of n can be 8, 16, 32, or 64. The following example declares one variable of each of the four types of sized integers:

__int8 nSmall;      // Declares 8-bit integer
__int16 nMedium;    // Declares 16-bit integer
__int32 nLarge;     // Declares 32-bit integer
__int64 nHuge;      // Declares 64-bit integer

The first three types of sized integers are synonyms for the ANSI types that have the same size, and are useful for writing portable code that behaves identically across multiple platforms. Note that the __int8 data type is synonymous with type char, __int16 is synonymous with type short, and __int32 is synonymous with type int. The __int64 type has no equivalent ANSI counterpart.

END Microsoft Specific


Type float

Floating-point numbers use the IEEE (Institute of Electrical and Electronics Engineers) format. Single-precision values with float type have 4 bytes, consisting of a sign bit, an 8-bit excess-127 binary exponent, and a 23-bit mantissa. The mantissa represents a number between 1.0 and 2.0. Since the high-order bit of the mantissa is always 1, it is not stored in the number. This representation gives a range of approximately 3.4E–38 to 3.4E+38 for type float.

You can declare variables as float or double, depending on the needs of your application. The principal differences between the two types are the significance they can represent, the storage they require, and their range. Table 3.3 shows the relationship between significance and storage requirements.

Table 3.3 Floating-Point Types

Type | Significant digits | Number of bytes
float | 6 – 7 | 4
double | 15 – 16 | 8

Floating-point variables are represented by a mantissa, which contains the value of the number, and an exponent, which contains the order of magnitude of the number.

Table 3.4 shows the number of bits allocated to the mantissa and the exponent for each floating-point type. The most significant bit of any float or double is always the sign bit. If it is 1, the number is considered negative; otherwise, it is considered a positive number.

Table 3.4 Lengths of Exponents and Mantissas

Type | Exponent length | Mantissa length
float | 8 bits | 23 bits
double | 11 bits | 52 bits

Because exponents are stored in an unsigned form, the exponent is biased by half its possible value. For type float, the bias is 127; for type double, it is 1023. You can compute the actual exponent value by subtracting the bias value from the exponent value.

The mantissa is stored as a binary fraction greater than or equal to 1 and less than 2. For types float and double, there is an implied leading 1 in the mantissa in the most-significant bit position, so the mantissas are actually 24 and 53 bits long, respectively, even though the most-significant bit is never stored in memory.

Instead of the storage method just described, the floating-point package can store binary floating-point numbers as denormalized numbers. “Denormalized numbers” are nonzero floating-point numbers with reserved exponent values in which the most-significant bit of the mantissa is 0. By using the denormalized format, the range of a floating-point number can be extended at the cost of precision. You cannot control whether a floating-point number is represented in normalized or denormalized form; the floating-point package determines the representation. The floating-point package never uses a denormalized form unless the exponent becomes less than the minimum that can be represented in a normalized form.

Table 3.5 shows the minimum and maximum values you can store in variables of each floating-point type. The values listed in this table apply only to normalized floating-point numbers; denormalized floating-point numbers have a smaller minimum value. Note that numbers retained in 80x87 registers are always represented in 80-bit normalized form; numbers can only be represented in denormalized form when stored in 32-bit or 64-bit floating-point variables (variables of type float and type long).

Table 3.5 Range of Floating-Point Types

Type | Minimum value | Maximum value
float | 1.175494351 E – 38 | 3.402823466 E + 38
double | 2.2250738585072014 E – 308 | 1.7976931348623158 E + 308

If precision is less of a concern than storage, consider using type float for floating-point variables. Conversely, if precision is the most important criterion, use type double.

Floating-point variables can be promoted to a type of greater significance (from type float to type double). Promotion often occurs when you perform arithmetic on floating-point variables. This arithmetic is always done in as high a degree of precision as the variable with the highest degree of precision. For example, consider the following type declarations:

float f_short;
double f_long;
long double f_longer;

f_short = f_short * f_long;

In the preceding example, the variable f_short is promoted to type double and multiplied by f_long; then the result is rounded to type float before being assigned to f_short.

In the following example (which uses the declarations from the preceding example), the arithmetic is done in float (32-bit) precision on the variables; the result is then promoted to type double:

f_longer = f_short * f_short;


Type double

Double precision values with double type have 8 bytes. The format is similar to the float format except that it has an 11-bit excess-1023 exponent and a 52-bit mantissa, plus the implied high-order 1 bit. This format gives a range of approximately 1.7E–308 to 1.7E+308 for type double.

Microsoft Specific —>

The double type contains 64 bits: 1 for sign, 11 for the exponent, and 52 for the mantissa. Its range is +/–1.7E308 with at least 15 digits of precision.

END Microsoft Specific


Type long double

The range of values for a variable is bounded by the minimum and maximum values that can be represented internally in a given number of bits. However, because of C’s conversion rules (discussed in detail in Type Conversions in Chapter 4) you cannot always use the maximum or minimum value for a constant of a particular type in an expression.

For example, the constant expression -32768 consists of the arithmetic negation operator (–) applied to the constant value 32,768. Since 32,768 is too large to represent as a short int, it is given the long type. Consequently, the constant expression -32768 has long type. You can only represent –32,768 as a short int by type-casting it to the short type. No information is lost in the type cast, since –32,768 can be represented internally in 2 bytes.

The value 65,000 in decimal notation is considered a signed constant. It is given the long type because 65,000 does not fit into a short. A value such as 65,000 can only be represented as an unsigned short by type-casting the value to unsigned short type, by giving the value in octal or hexadecimal notation, or by specifying it as 65000U. You can cast this long value to the unsigned short type without loss of information, since 65,000 can fit in 2 bytes when it is stored as an unsigned number.

Microsoft Specific —>

The long double contains 80 bits: 1 for sign, 15 for exponent, and 64 for mantissa. Its range is +/–1.2E4932 with at least 19 digits of precision. Although long double and double are separate types, the representation of long double and double is identical.

END Microsoft Specific


Incomplete Types

An incomplete type is a type that describes an identifier but lacks information needed to determine the size of the identifier. An “incomplete type” can be:

  • A structure type whose members you have not yet specified.

  • A union type whose members you have not yet specified.

  • An array type whose dimension you have not yet specified.

The void type is an incomplete type that cannot be completed. To complete an incomplete type, specify the missing information. The following examples show how to create and complete the incomplete types.

  • To create an incomplete structure type, declare a structure type without specifying its members. In this example, the ps pointer points to an incomplete structure type called student.
    struct student *ps;
  • To complete an incomplete structure type, declare the same structure type later in the same scope with its members specified, as in
    struct student
{
    int num;
}                   /* student structure now completed */
  • To create an incomplete array type, declare an array type without specifying its repetition count. For example:
    char a[];  /* a has incomplete type */
  • To complete an incomplete array type, declare the same name later in the same scope with its repetition count specified, as in
    char a[25]; /* a now has complete type */


Typedef Declarations

A typedef declaration is a declaration with typedef as the storage class. The declarator becomes a new type. You can use typedef declarations to construct shorter or more meaningful names for types already defined by C or for types that you have declared. Typedef names allow you to encapsulate implementation details that may change.

A typedef declaration is interpreted in the same way as a variable or function declaration, but the identifier, instead of assuming the type specified by the declaration, becomes a synonym for the type.

Syntax

declaration :

declaration-specifiers init-declarator-list opt ;

declaration-specifiers :

storage-class-specifier declaration-specifiers opt
type-specifier declaration-specifiers opt
type-qualifier declaration-specifiers opt

storage-class-specifier :

typedef

type-specifier :

void
char
short
int
long
float
double
signed
unsigned
struct-or-union-specifier
enum-specifier
typedef-name

typedef-name :

identifier

Note that a typedef declaration does not create types. It creates synonyms for existing types, or names for types that could be specified in other ways. When a typedef name is used as a type specifier, it can be combined with certain type specifiers, but not others. Acceptable modifiers include const and volatile.

Typedef names share the name space with ordinary identifiers (see Name Spaces in Chapter 2 for more information). Therefore, a program can have a typedef name and a local-scope identifier by the same name. For example:

typedef char FlagType;

int main()
{
}

int myproc( int )
{
    int FlagType;
}

When declaring a local-scope identifier by the same name as a typedef, or when declaring a member of a structure or union in the same scope or in an inner scope, the type specifier must be specified. This example illustrates this constraint:

typedef char FlagType;
const FlagType x;

To reuse the FlagType name for an identifier, a structure member, or a union member, the type must be provided:

const int FlagType;  /* Type specifier required */

It is not sufficient to say

const FlagType;      /* Incomplete specification */

because the FlagType is taken to be part of the type, not an identifier that is being redeclared. This declaration is taken to be an illegal declaration like

int;  /* Illegal declaration */

You can declare any type with typedef, including pointer, function, and array types. You can declare a typedef name for a pointer to a structure or union type before you define the structure or union type, as long as the definition has the same visibility as the declaration.

Typedef names can be used to improve code readability. All three of the following declarations of signal specify exactly the same type, the first without making use of any typedef names.

typedef void fv( int ), (*pfv)( int );  /* typedef declarations */

void ( *signal( int, void (*) (int)) ) ( int );
fv *signal( int, fv * );   /* Uses typedef type */
pfv signal( int, pfv );    /* Uses typedef type */

Examples

The following examples illustrate typedef declarations:

typedef int WHOLE; /* Declares WHOLE to be a synonym for int */

Note that WHOLE could now be used in a variable declaration such as WHOLE i; or const WHOLE i;. However, the declaration long WHOLE i; would be illegal.

typedef struct club
{
    char name[30];
    int size, year;
} GROUP;

This statement declares GROUP as a structure type with three members. Since a structure tag, club, is also specified, either the typedef name (GROUP) or the structure tag can be used in declarations. You must use the struct keyword with the tag, and you cannot use the struct keyword with the typedef name.

typedef GROUP *PG; /* Uses the previous typedef name
                      to declare a pointer            */

The type PG is declared as a pointer to the GROUP type, which in turn is defined as a structure type.

typedef void DRAWF( int, int );

This example provides the type DRAWF for a function returning no value and taking two int arguments. This means, for example, that the declaration

DRAWF box;

is equivalent to the declaration

void box( int, int );


C Extended Storage-Class Attributes

Microsoft Specific —>

Extended attribute syntax simplifies and standardizes the Microsoft-specific extensions to the C language. The storage-class attributes that use extended attribute syntax include thread, naked, dllimport, and dllexport.

The extended attribute syntax for specifying storage-class information uses the __declspec keyword, which specifies that an instance of a given type is to be stored with a Microsoft-specific storage-class attribute (thread, naked, dllimport, or dllexport). Examples of other storage-class modifiers include the static and extern keywords. However, these keywords are part of the ANSI C standard and as such are not covered by extended attribute syntax.

Syntax

storage-class-specifier :

__declspec ( extended-decl-modifier-seq ) /* Microsoft Specific */

extended-decl-modifier-seq :

extended-decl-modifier opt
extended-decl-modifier-seq extended-decl-modifier

extended-decl-modifier :

thread
naked
dllimport
dllexport

White space separates the declaration modifiers. Note that extended-decl-modifier-seq can be empty; in this case, __declspec has no effect.

The thread, naked, dllimport, and dllexport storage-class attributes are a property only of the declaration of the data or function to which they are applied; they do not redefine the type attributes of the function itself. The thread attribute affects data only. The naked attribute affects functions only. The dllimport and dllexport attributes affect functions and data.

END Microsoft Specific


DLL Import and Export

Microsoft Specific —>

The dllimport and dllexport storage-class modifiers are Microsoft-specific extensions to the C language. These modifiers define the DLL’s interface to its client (the executable file or another DLL). For specific information about using these modifiers, see DLL Import and Export Functions in Chapter 6.

END Microsoft Specific


Naked

Microsoft Specific —>

The naked storage-class attribute is a Microsoft-specific extension to the C language. The compiler generates code without prolog and epilog code for functions declared with the naked storage-class attribute. Naked functions are useful when you need to write your own prolog/epilog code sequences using inline assembler code. Naked functions are useful for writing virtual device drivers.

For specific information about using the naked attribute, see Naked Functions in Chapter 6.

END Microsoft Specific


Thread Local Storage

Microsoft Specific —>

Thread Local Storage (TLS) is the mechanism by which each thread in a given multithreaded process allocates storage for thread-specific data. In standard multithreaded programs, data is shared among all threads of a given process, whereas thread local storage is the mechanism for allocating per-thread data. For a complete discussion of threads, see Processes and Threads in the Microsoft Win32® Software Development Kit documentation.

The Microsoft C language includes the extended storage-class attribute, thread, which is used with the __declspec keyword to declare a thread local variable. For example, the following code declares an integer thread local variable and initializes it with a value:

__declspec( thread ) int tls_i = 1;

These guidelines must be observed when you are declaring statically bound thread local variables:

  • The use of __declspec(thread) may interfere with delay loading of DLL imports.

  • You can apply the thread attribute only to data declarations and definitions. It cannot be used on function declarations or definitions. For example, the following code generates a compiler error:
    #define Thread    __declspec( thread )
Thread void func();        /* Error */
  • You can specify the thread attribute only on data items with static storage duration. This includes global data (both static and extern) and local static data. You cannot declare automatic data with the thread attribute. For example, the following code generates compiler errors:
    #define Thread    __declspec( thread )
void func1()
{
    Thread int tls_i;            /* Error */
}

int func2( Thread int tls_i )    /* Error */
{
return tls_i;
}
  • You must use the thread attribute for the declaration and the definition of thread local data, regardless of whether the declaration and definition occur in the same file or separate files. For example, the following code generates an error:
    #define Thread    __declspec( thread )
extern int tls_i;     /* This generates an error, because the   */
int Thread tls_i;     /* declaration and the definition differ. */
  • You cannot use the thread attribute as a type modifier. For example, the following code generates a compiler error:
    char *ch __declspec( thread );        /* Error */
  • The address of a thread local variable is not considered constant, and any expression involving such an address is not considered a constant expression. This means that you cannot use the address of a thread local variable as an initializer for a pointer. For example, the compiler flags the following code as an error:
    #define Thread    __declspec( thread )
Thread int tls_i;
int *p = &tls_i;        /* Error */
  • C permits initialization of a variable with an expression involving a reference to itself, but only for objects of nonstatic extent. For example:
    #define Thread    __declspec( thread )
Thread int tls_i = tls_i;             /* Error */
int j = j;                            /* Error */
Thread int tls_i = sizeof( tls_i )    /* Okay  */

    Note that a sizeof expression that includes the variable being initialized does not constitute a reference to itself and is allowed.

  • The use of __declspec(thread) may interfere with delay loading of DLL imports.

For more information about using the thread attribute, see Multithreading Topics in Visual C++ Programmer’s Guide.

END Microsoft Specific


Expressions and Assignments

This chapter describes how to form expressions and to assign values in the C language. Constants, identifiers, strings, and function calls are all operands that are manipulated in expressions. The C language has all the usual language operators. This chapter covers those operators as well as operators that are unique to C or Microsoft C. The topics discussed include:

  • L-value and r-value expressions

  • Constant expressions

  • Side effects

  • Sequence points

  • Operators

  • Operator precedence

  • Type conversions

  • Type casts


Operands and Expressions

An “operand” is an entity on which an operator acts. An “expression” is a sequence of operators and operands that performs any combination of these actions:

  • Computes a value

  • Designates an object or function

  • Generates side effects

Operands in C include constants, identifiers, strings, function calls, subscript expressions, member-selection expressions, and complex expressions formed by combining operands with operators or by enclosing operands in parentheses. The syntax for these operands is given in Primary Expressions.


C Primary Expressions

The operands in expressions are called “primary expressions.”

Syntax

primary-expression :

identifier
constant
string-literal
( expression )

expression :

assignment-expression
expression , assignment-expression


Identifiers in Primary Expressions

Identifiers can have integral, float, enum, struct, union, array, pointer, or function type. An identifier is a primary expression provided it has been declared as designating an object (in which case it is an l-value) or as a function (in which case it is a function designator). See L-Value and R-Value Expressions for a definition of l-value.

The pointer value represented by an array identifier is not a variable, so an array identifier cannot form the left-hand operand of an assignment operation and therefore is not a modifiable l-value.

An identifier declared as a function represents a pointer whose value is the address of the function. The pointer addresses a function returning a value of a specified type. Thus, function identifiers also cannot be l-values in assignment operations. For more information, see Identifiers in Chapter 1.


Constants in Primary Expressions

A constant operand has the value and type of the constant value it represents. A character constant has int type. An integer constant has int, long, unsigned int, or unsigned long type, depending on the integer’s size and on the way the value is specified. See Constants in Chapter 1 for more information.


String Literals in Primary Expressions

A “string literal” is a character, wide character, or sequence of adjacent characters enclosed in double quotation marks. Since they are not variables, neither string literals nor any of their elements can be the left-hand operand in an assignment operation. The type of a string literal is an array of char (or an array of wchar_t for wide-string literals). Arrays in expressions are converted to pointers. See String Literals in Chapter 1 for more information about strings.


Expressions in Parentheses

You can enclose any operand in parentheses without changing the type or value of the enclosed expression. For example, in the expression:

( 10 + 5 ) / 5

the parentheses around 10 + 5 mean that the value of 10 + 5 is evaluated first and it becomes the left operand of the division (/) operator. The result of ( 10 + 5 ) / 5 is 3. Without the parentheses, 10 + 5 / 5 would evaluate to 11.

Although parentheses affect the way operands are grouped in an expression, they cannot guarantee a particular order of evaluation in all cases. For example, neither the parentheses nor the left-to-right grouping of the following expression guarantees what the value of i will be in either of the subexpressions:

( i++ +1 ) * ( 2 + i )

The compiler is free to evaluate the two sides of the multiplication in any order. If the initial value of i is zero, the whole expression could be evaluated as either of these two statements:

( 0 + 1 + 1 ) * ( 2 + 1 )
( 0 + 1 + 1 ) * ( 2 + 0 )

Exceptions resulting from side effects are discussed in Side Effects.


L-Value and R-Value Expressions

Expressions that refer to memory locations are called “l-value” expressions. An l-value represents a storage region’s “locator” value, or a “left” value, implying that it can appear on the left of the equal sign (=). L-values are often identifiers.

Expressions referring to modifiable locations are called “modifiable l-values.” A modifiable l-value cannot have an array type, an incomplete type, or a type with the const attribute. For structures and unions to be modifiable l-values, they must not have any members with the const attribute. The name of the identifier denotes a storage location, while the value of the variable is the value stored at that location.

An identifier is a modifiable l-value if it refers to a memory location and if its type is arithmetic, structure, union, or pointer. For example, if ptr is a pointer to a storage region, then *ptr is a modifiable l-value that designates the storage region to which ptr points.

Any of the following C expressions can be l-value expressions:

  • An identifier of integral, floating, pointer, structure, or union type

  • A subscript ([ ]) expression that does not evaluate to an array

  • A member-selection expression (–> or .)

  • A unary-indirection (*) expression that does not refer to an array

  • An l-value expression in parentheses

  • A const object (a nonmodifiable l-value)

The term “r-value” is sometimes used to describe the value of an expression and to distinguish it from an l-value. All l-values are r-values but not all r-values are l-values.

Microsoft Specific —>

Microsoft C includes an extension to the ANSI C standard that allows casts of l-values to be used as l-values, as long as the size of the object is not lengthened through the cast. (See Type-Cast Conversions for more information.) The following example illustrates this feature:

char *p ;
short  i;
long l;

(long *) p = &l ;       /* Legal cast   */
(long) i = l ;          /* Illegal cast */

The default for Microsoft C is that the Microsoft extensions are enabled. Use the /Za compiler option to disable these extensions.

END Microsoft Specific


C Constant Expressions

A constant expression is evaluated at compile time, not run time, and can be used in any place that a constant can be used. The constant expression must evaluate to a constant that is in the range of representable values for that type. The operands of a constant expression can be integer constants, character constants, floating-point constants, enumeration constants, type casts, sizeof expressions, and other constant expressions.

Syntax

constant-expression :

conditional-expression

conditional-expression :

logical-OR-expression
logical-OR-expression ? expression : conditional-expression

expression :

assignment-expression
expression , assignment-expression

assignment-expression :

conditional-expression
unary-expression assignment-operator assignment-expression

assignment-operator : one of

= *= /= %= += –= <<= >>= &= ^= |=

The nonterminals for struct declarator, enumerator, direct declarator, direct-abstract declarator, and labeled statement contain the constant-expression nonterminal.

An integral constant expression must be used to specify the size of a bit-field member of a structure, the value of an enumeration constant, the size of an array, or the value of a case constant.

Constant expressions used in preprocessor directives are subject to additional restrictions. Consequently, they are known as “restricted constant expressions.” A restricted constant expression cannot contain sizeof expressions, enumeration constants, type casts to any type, or floating-type constants. It can, however, contain the special constant expression defined (identifier).


Expression Evaluation

Expressions involving assignment, unary increment, unary decrement, or calling a function may have consequences incidental to their evaluation (side effects). When a “sequence point” is reached, everything preceding the sequence point, including any side effects, is guaranteed to have been evaluated before evaluation begins on anything following the sequence point.

“Side effects” are changes caused by the evaluation of an expression. Side effects occur whenever the value of a variable is changed by an expression evaluation. All assignment operations have side effects. Function calls can also have side effects if they change the value of an externally visible item, either by direct assignment or by indirect assignment through a pointer.


Side Effects

The order of evaluation of expressions is defined by the specific implementation, except when the language guarantees a particular order of evaluation (as outlined in Precedence and Order of Evaluation). For example, side effects occur in the following function calls:

add( i + 1, i = j + 2 );
myproc( getc(), getc() );

The arguments of a function call can be evaluated in any order. The expression i + 1 may be evaluated before i = j + 2, or i = j + 2 may be evaluated before i + 1. The result is different in each case. Likewise, it is not possible to guarantee what characters are actually passed to the myproc. Since unary increment and decrement operations involve assignments, such operations can cause side effects, as shown in the following example:

x[i] = i++;

In this example, the value of x that is modified is unpredictable. The value of the subscript could be either the new or the old value of i. The result can vary under different compilers or different optimization levels.

Since C does not define the order of evaluation of side effects, both evaluation methods discussed above are correct and either may be implemented. To make sure that your code is portable and clear, avoid statements that depend on a particular order of evaluation for side effects.


C Sequence Points

Between consecutive “sequence points” an object’s value can be modified only once by an expression. The C language defines the following sequence points:

  • Left operand of the logical-AND operator (&&). The left operand of the logical-AND operator is completely evaluated and all side effects complete before continuing. If the left operand evaluates to false (0), the other operand is not evaluated.

  • Left operand of the logical-OR operator (||). The left operand of the logical-OR operator is completely evaluated and all side effects complete before continuing. If the left operand evaluates to true (nonzero), the other operand is not evaluated.

  • Left operand of the comma operator. The left operand of the comma operator is completely evaluated and all side effects complete before continuing. Both operands of the comma operator are always evaluated. Note that the comma operator in a function call does not guarantee an order of evaluation.

  • Function-call operator. All arguments to a function are evaluated and all side effects complete before entry to the function. No order of evaluation among the arguments is specified.

  • First operand of the conditional operator. The first operand of the conditional operator is completely evaluated and all side effects complete before continuing.

  • The end of a full initialization expression (that is, an expression that is not part of another expression such as the end of an initialization in a declaration statement).

  • The expression in an expression statement. Expression statements consist of an optional expression followed by a semicolon (;). The expression is evaluated for its side effects and there is a sequence point following this evaluation.

  • The controlling expression in a selection (if or switch) statement. The expression is completely evaluated and all side effects complete before the code dependent on the selection is executed.

  • The controlling expression of a while or do statement. The expression is completely evaluated and all side effects complete before any statements in the next iteration of the while or do loop are executed.

  • Each of the three expressions of a for statement. The expressions are completely evaluated and all side effects complete before any statements in the next iteration of the for loop are executed.

  • The expression in a return statement. The expression is completely evaluated and all side effects complete before control returns to the calling function.


C Operators

There are three types of operators. A unary expression consists of either a unary operator prepended to an operand, or the sizeof keyword followed by an expression. The expression can be either the name of a variable or a cast expression. If the expression is a cast expression, it must be enclosed in parentheses. A binary expression consists of two operands joined by a binary operator. A ternary expression consists of three operands joined by the conditional-expression operator.

C includes the following unary operators:

Symbol | Name
– ~ ! | Negation and complement operators
* & | Indirection and address-of operators
sizeof | Size operator
+ | Unary plus operator
++ –– | Unary increment and decrement operators

Binary operators associate from left to right. C provides the following binary operators:

Symbol | Name
* / % | Multiplicative operators
+ – | Additive operators
<< >> | Shift operators
< > <= >= == != | Relational operators
& | ^ | Bitwise operators
&& || | Logical operators
, | Sequential-evaluation operator

The conditional-expression operator has lower precedence than binary expressions and differs from them in being right associative.

Expressions with operators also include assignment expressions, which use unary or binary assignment operators. The unary assignment operators are the increment (++) and decrement (––) operators; the binary assignment operators are the simple-assignment operator (=) and the compound-assignment operators. Each compound-assignment operator is a combination of another binary operator with the simple-assignment operator.


Precedence and Order of Evaluation

The precedence and associativity of C operators affect the grouping and evaluation of operands in expressions. An operator’s precedence is meaningful only if other operators with higher or lower precedence are present. Expressions with higher-precedence operators are evaluated first. Precedence can also be described by the word “binding.” Operators with a higher precedence are said to have tighter binding.

Table 4.1 summarizes the precedence and associativity (the order in which the operands are evaluated) of C operators, listing them in order of precedence from highest to lowest. Where several operators appear together, they have equal precedence and are evaluated according to their associativity. The operators in the table are described in the sections beginning with Postfix Operators. The rest of this section gives general information about precedence and associativity.

Table 4.1 Precedence and Associativity of C Operators

Symbol1 | Type of Operation | Associativity
[ ] ( ) . –> postfix ++ and postfix –– | Expression | Left to right
prefix ++ and prefix –– sizeof & * + – ~ ! | Unary | Right to left
typecasts | Unary | Right to left
* / % | Multiplicative | Left to right
+ – | Additive | Left to right
<< >> | Bitwise shift | Left to right
< > <= >= | Relational | Left to right
== != | Equality | Left to right
& | Bitwise-AND | Left to right
^ | Bitwise-exclusive-OR | Left to right
| | Bitwise-inclusive-OR | Left to right
&& | Logical-AND | Left to right
|| | Logical-OR | Left to right
? : | Conditional-expression | Right to left
= *= /= %= += –= <<= >>= &= ^= |= | Simple and compound assignment2 | Right to left
, | Sequential evaluation | Left to right

1. Operators are listed in descending order of precedence. If several operators appear on the same line or in a group, they have equal precedence.

2. All simple and compound-assignment operators have equal precedence.

An expression can contain several operators with equal precedence. When several such operators appear at the same level in an expression, evaluation proceeds according to the associativity of the operator, either from right to left or from left to right. The direction of evaluation does not affect the results of expressions that include more than one multiplication (*), addition (+), or binary-bitwise (& | ^) operator at the same level. Order of operations is not defined by the language. The compiler is free to evaluate such expressions in any order, if the compiler can guarantee a consistent result.

Only the sequential-evaluation (,), logical-AND (&&), logical-OR (||), conditional-expression (? :), and function-call operators constitute sequence points and therefore guarantee a particular order of evaluation for their operands. The function-call operator is the set of parentheses following the function identifier. The sequential-evaluation operator (,) is guaranteed to evaluate its operands from left to right. (Note that the comma operator in a function call is not the same as the sequential-evaluation operator and does not provide any such guarantee.) For more information, see Sequence Points.

Logical operators also guarantee evaluation of their operands from left to right. However, they evaluate the smallest number of operands needed to determine the result of the expression. This is called “short-circuit” evaluation. Thus, some operands of the expression may not be evaluated. For example, in the expression

x && y++

the second operand, y++, is evaluated only if x is true (nonzero). Thus, y is not incremented if x is false (0).

Examples

The following list shows how the compiler automatically binds several sample expressions:

Expression | Automatic Binding
a & b || c | (a & b) || c
a = b || c | a = (b || c)
q && r || s-- | (q && r) || s––

In the first expression, the bitwise-AND operator (&) has higher precedence than the logical-OR operator (||), so a & b forms the first operand of the logical-OR operation.

In the second expression, the logical-OR operator (||) has higher precedence than the simple-assignment operator (=), so b || c is grouped as the right-hand operand in the assignment. Note that the value assigned to a is either 0 or 1.

The third expression shows a correctly formed expression that may produce an unexpected result. The logical-AND operator (&&) has higher precedence than the logical-OR operator (||), so q && r is grouped as an operand. Since the logical operators guarantee evaluation of operands from left to right, q && r is evaluated before s––. However, if q && r evaluates to a nonzero value, s–– is not evaluated, and s is not decremented. If not decrementing s would cause a problem in your program, s–– should appear as the first operand of the expression, or s should be decremented in a separate operation.

The following expression is illegal and produces a diagnostic message at compile time:

Illegal Expression | Default Grouping
p == 0 ? p += 1: p += 2 | ( p == 0 ? p += 1 : p ) += 2

In this expression, the equality operator (==) has the highest precedence, so p == 0 is grouped as an operand. The conditional-expression operator (? :) has the next-highest precedence. Its first operand is p == 0, and its second operand is p += 1. However, the last operand of the conditional-expression operator is considered to be p rather than p += 2, since this occurrence of p binds more closely to the conditional-expression operator than it does to the compound-assignment operator. A syntax error occurs because += 2 does not have a left-hand operand. You should use parentheses to prevent errors of this kind and produce more readable code. For example, you could use parentheses as shown below to correct and clarify the preceding example:

( p == 0 ) ? ( p += 1 ) : ( p += 2 )


Usual Arithmetic Conversions

Most C operators perform type conversions to bring the operands of an expression to a common type or to extend short values to the integer size used in machine operations. The conversions performed by C operators depend on the specific operator and the type of the operand or operands. However, many operators perform similar conversions on operands of integral and floating types. These conversions are known as “arithmetic conversions.” Conversion of an operand value to a compatible type causes no change to its value.

The arithmetic conversions summarized below are called “usual arithmetic conversions.” These steps are applied only for binary operators that expect arithmetic type and only if the two operands do not have the same type. The purpose is to yield a common type which is also the type of the result. To determine which conversions actually take place, the compiler applies the following algorithm to binary operations in the expression. The steps below are not a precedence order.

  1. If either operand is of type long double, the other operand is converted to type long double.

  2. If the above condition is not met and either operand is of type double, the other operand is converted to type double.

  3. If the above two conditions are not met and either operand is of type float, the other operand is converted to type float.

  4. If the above three conditions are not met (none of the operands are of floating types), then integral conversions are performed on the operands as follows:
    • If either operand is of type unsigned long, the other operand is converted to type unsigned long.

    • If the above condition is not met and either operand is of type long and the other of type unsigned int, both operands are converted to type unsigned long.

    • If the above two conditions are not met, and either operand is of type long, the other operand is converted to type long.

    • If the above three conditions are not met, and either operand is of type unsigned int, the other operand is converted to type unsigned int.

    • If none of the above conditions are met, both operands are converted to type int.

The following code illustrates these conversion rules:

float   fVal;
double  dVal;
int   iVal;
unsigned long ulVal;

dVal = iVal * ulVal; /* iVal converted to unsigned long
                      * Uses step 4.
                      * Result of multiplication converted to double
                      */
dVal = ulVal + fVal; /* ulVal converted to float
                      * Uses step 3.
                      * Result of addition converted to double
                      */


Postfix Operators

The postfix operators have the highest precedence (the tightest binding) in expression evaluation.

Syntax

postfix-expression :

primary-expression
postfix-expression [ expression ]
postfix-expression ( argument-expression-list opt )
postfix-expression . identifier
postfix-expression –> identifier
postfix-expression ++
postfix-expression ––

Operators in this precedence level are the array subscripts, function calls, structure and union members, and postfix increment and decrement operators.


One-Dimensional Arrays

A postfix expression followed by an expression in square brackets ([ ]) is a subscripted representation of an element of an array object. A subscript expression represents the value at the address that is expression positions beyond postfix-expression when expressed as

postfix-expression [ expression ]

Usually, the value represented by postfix-expression is a pointer value, such as an array identifier, and expression is an integral value. However, all that is required syntactically is that one of the expressions be of pointer type and the other be of integral type. Thus the integral value could be in the postfix-expression position and the pointer value could be in the brackets in the expression, or “subscript,” position. For example, this code is legal:

int sum, *ptr, a[10];

int main()
{
    ptr = a;
    sum = 4[ptr];
}

Subscript expressions are generally used to refer to array elements, but you can apply a subscript to any pointer. Whatever the order of values, expression must be enclosed in brackets ([ ]).

The subscript expression is evaluated by adding the integral value to the pointer value, then applying the indirection operator (*) to the result. (See Indirection and Address-of Operators for a discussion of the indirection operator.) In effect, for a one-dimensional array, the following four expressions are equivalent, assuming that a is a pointer and b is an integer:

a[b]
*(a + b)
*(b + a)
b[a]

According to the conversion rules for the addition operator (given in Additive Operators), the integral value is converted to an address offset by multiplying it by the length of the type addressed by the pointer.

For example, suppose the identifier line refers to an array of int values. The following procedure is used to evaluate the subscript expression line[ i ]:

  1. The integer value i is multiplied by the number of bytes defined as the length of an int item. The converted value of i represents i int positions.

  2. This converted value is added to the original pointer value (line) to yield an address that is offset i int positions from line.

  3. The indirection operator is applied to the new address. The result is the value of the array element at that position (intuitively, line [ i ]).

The subscript expression line[0] represents the value of the first element of line, since the offset from the address represented by line is 0. Similarly, an expression such as line[5] refers to the element offset five positions from line, or the sixth element of the array.


Multidimensional Arrays

A subscript expression can also have multiple subscripts, as follows:

expression1 [expression2] [expression3]...

Subscript expressions associate from left to right. The leftmost subscript expression, expression1[expression2], is evaluated first. The address that results from adding expression1 and expression2 forms a pointer expression; then expression3 is added to this pointer expression to form a new pointer expression, and so on until the last subscript expression has been added. The indirection operator (*) is applied after the last subscripted expression is evaluated, unless the final pointer value addresses an array type (see examples below).

Expressions with multiple subscripts refer to elements of “multidimensional arrays.” A multidimensional array is an array whose elements are arrays. For example, the first element of a three-dimensional array is an array with two dimensions.

Examples

For the following examples, an array named prop is declared with three elements, each of which is a 4-by-6 array of int values.

int prop[3][4][6];
int i, *ip, (*ipp)[6];

A reference to the prop array looks like this:

i = prop[0][0][1];

The example above shows how to refer to the second individual int element of prop. Arrays are stored by row, so the last subscript varies most quickly; the expression prop[0][0][2] refers to the next (third) element of the array, and so on.

i = prop[2][1][3];

This statement is a more complex reference to an individual element of prop. The expression is evaluated as follows:

  1. The first subscript, 2, is multiplied by the size of a 4-by-6 int array and added to the pointer value prop. The result points to the third 4-by-6 array of prop.

  2. The second subscript, 1, is multiplied by the size of the 6-element int array and added to the address represented by prop[2].

  3. Each element of the 6-element array is an int value, so the final subscript, 3, is multiplied by the size of an int before it is added to prop[2][1]. The resulting pointer addresses the fourth element of the 6-element array.

  4. The indirection operator is applied to the pointer value. The result is the int element at that address.

These next two examples show cases where the indirection operator is not applied.

ip = prop[2][1];

ipp = prop[2];

In the first of these statements, the expression prop[2][1] is a valid reference to the three-dimensional array prop; it refers to a 6-element array (declared above). Since the pointer value addresses an array, the indirection operator is not applied.

Similarly, the result of the expression prop[2] in the second statement ipp = prop[2]; is a pointer value addressing a two-dimensional array.


Function Call

A “function call” is an expression that includes the name of the function being called or the value of a function pointer and, optionally, the arguments being passed to the function.

Syntax

postfix-expression :

postfix-expression ( argument-expression-list opt )

argument-expression-list :

assignment-expression
argument-expression-list , assignment-expression

The postfix-expression must evaluate to a function address (for example, a function identifier or the value of a function pointer), and argument-expression-list is a list of expressions (separated by commas) whose values (the “arguments”) are passed to the function. The argument-expression-list argument can be empty.

A function-call expression has the value and type of the function’s return value. A function cannot return an object of array type. If the function’s return type is void (that is, the function has been declared never to return a value), the function-call expression also has void type. (See Function Calls in Chapter 6 for more information.)


Structure and Union Members

A “member-selection expression” refers to members of structures and unions. Such an expression has the value and type of the selected member.

Syntax

postfix-expression . identifier
postfix-expression –> identifier

This list describes the two forms of the member-selection expressions:

  1. In the first form, postfix-expression represents a value of struct or union type, and identifier names a member of the specified structure or union. The value of the operation is that of identifier and is an l-value if postfix-expression is an l-value. See L-Value and R-Value Expressions for more information.

  2. In the second form, postfix-expression represents a pointer to a structure or union, and identifier names a member of the specified structure or union. The value is that of identifier and is an l-value.

The two forms of member-selection expressions have similar effects.

In fact, an expression involving the member-selection operator (–>) is a shorthand version of an expression using the period (.) if the expression before the period consists of the indirection operator (*) applied to a pointer value. Therefore,

expression –> identifier

is equivalent to

(*expression) . identifier

when expression is a pointer value.

Examples

The following examples refer to this structure declaration. For information about the indirection operator (*) used in these examples, see Indirection and Address-of Operators.

struct pair
{
    int a;
    int b;
    struct pair *sp;
} item, list[10];

A member-selection expression for the item structure looks like this:

item.sp = &item;

In the example above, the address of the item structure is assigned to the sp member of the structure. This means that item contains a pointer to itself.

(item.sp)–>a = 24;

In this example, the pointer expression item.sp is used with the member-selection operator (–>) to assign a value to the member a.

list[8].b = 12;

This statement shows how to select an individual structure member from an array of structures.


C Postfix Increment and Decrement Operators

Operands of the postfix increment and decrement operators are scalar types that are modifiable l-values.

Syntax

postfix-expression :

postfix-expression ++
postfix-expression ––

The result of the postfix increment or decrement operation is the value of the operand. After the result is obtained, the value of the operand is incremented (or decremented). The following code illustrates the postfix increment operator.

if( var++ > 0 )
    *p++ = *q++;

In this example, the variable var is compared to 0, then incremented. If var was positive before being incremented, the next statement is executed. First, the value of the object pointed to by q is assigned to the object pointed to by p. Then, q and p are incremented.


C Unary Operators

Unary operators appear before their operand and associate from right to left.

Syntax

unary-expression :

postfix-expression
++ unary-expression
-- unary-expression
unary-operator cast-expression
sizeof unary-expression
sizeof ( type-name )

unary-operator : one of

& * + – ~ !


Prefix Increment and Decrement Operators

The unary operators (++ and ––) are called “prefix” increment or decrement operators when the increment or decrement operators appear before the operand. Postfix increment and decrement has higher precedence than prefix increment and decrement. The operand must have integral, floating, or pointer type and must be a modifiable l-value expression (an expression without the const attribute). The result is an l-value.

When the operator appears before its operand, the operand is incremented or decremented and its new value is the result of the expression.

An operand of integral or floating type is incremented or decremented by the integer value 1. The type of the result is the same as the operand type. An operand of pointer type is incremented or decremented by the size of the object it addresses. An incremented pointer points to the next object; a decremented pointer points to the previous object.

Example

This example illustrates the unary prefix decrement operator:

if( line[--i] != '\n' )
    return;

In this example, the variable i is decremented before it is used as a subscript to line.


Indirection and Address-of Operators

The indirection operator (*) accesses a value indirectly, through a pointer. The operand must be a pointer value. The result of the operation is the value addressed by the operand; that is, the value at the address to which its operand points. The type of the result is the type that the operand addresses.

If the operand points to a function, the result is a function designator. If it points to a storage location, the result is an l-value designating the storage location.

If the pointer value is invalid, the result is undefined. The following list includes some of the most common conditions that invalidate a pointer value.

  • The pointer is a null pointer.

  • The pointer specifies the address of a local item that is not visible at the time of the reference.

  • The pointer specifies an address that is inappropriately aligned for the type of the object pointed to.

  • The pointer specifies an address not used by the executing program.

The address-of operator (&) gives the address of its operand. The operand of the address-of operator can be either a function designator or an l-value that designates an object that is not a bit field and is not declared with the register storage-class specifier.

The result of the address operation is a pointer to the operand. The type addressed by the pointer is the type of the operand.

The address-of operator can only be applied to variables with fundamental, structure, or union types that are declared at the file-scope level, or to subscripted array references. In these expressions, a constant expression that does not include the address-of operator can be added to or subtracted from the address expression.

Examples

The following examples use these declarations:

int *pa, x;
int a[20];
double d;

This statement uses the address-of operator:

pa = &a[5];

The address-of operator (&) takes the address of the sixth element of the array a. The result is stored in the pointer variable pa.

x = *pa;

The indirection operator (*) is used in this example to access the int value at the address stored in pa. The value is assigned to the integer variable x.

if( x == *&x )
    printf( "True\n" );

This example prints the word True, demonstrating that the result of applying the indirection operator to the address of x is the same as x.

int roundup( void );     /* Function declaration */

int  *proundup  = roundup;
int  *pround  = &roundup;

Once the function roundup is declared, two pointers to roundup are declared and initialized. The first pointer, proundup, is initialized using only the name of the function, while the second, pround, uses the address-of operator in the initialization. The initializations are equivalent.


Unary Arithmetic Operators

The C unary plus, arithmetic-negation, complement, and logical-negation operators are discussed in the following list:

Operator | Description
+ | The unary plus operator preceding an expression in parentheses forces the grouping of the enclosed operations. It is used with expressions involving more than one associative or commutative binary operator. The operand must have arithmetic type. The result is the value of the operand. An integral operand undergoes integral promotion. The type of the result is the type of the promoted operand.
– | The arithmetic-negation operator produces the negative (two’s complement) of its operand. The operand must be an integral or floating value. This operator performs the usual arithmetic conversions.
~ | The bitwise-complement (or bitwise-NOT) operator produces the bitwise complement of its operand. The operand must be of integral type. This operator performs usual arithmetic conversions; the result has the type of the operand after conversion.
! | The logical-negation (logical-NOT) operator produces the value 0 if its operand is true (nonzero) and the value 1 if its operand is false (0). The result has int type. The operand must be an integral, floating, or pointer value.

Unary arithmetic operations on pointers are illegal.

Examples

The following examples illustrate the unary arithmetic operators:

short x = 987;
    x = -x;

In the example above, the new value of x is the negative of 987, or –987.

unsigned short y = 0xAAAA;
    y = ~y;

In this example, the new value assigned to y is the one’s complement of the unsigned value 0xAAAA, or 0x5555.

if( !(x < y) )

If x is greater than or equal to y, the result of the expression is 1 (true). If x is less than y, the result is 0 (false).


The sizeof Operator

The sizeof operator gives the amount of storage, in bytes, required to store an object of the type of the operand. This operator allows you to avoid specifying machine-dependent data sizes in your programs.

Syntax

sizeof unary-expression

sizeof ( type-name )

The operand is either an identifier that is a unary-expression, or a type-cast expression (that is, a type specifier enclosed in parentheses). The unary-expression cannot represent a bit-field object, an incomplete type, or a function designator. The result is an unsigned integral constant. The standard header STDDEF.H defines this type as size_t.

When you apply the sizeof operator to an array identifier, the result is the size of the entire array rather than the size of the pointer represented by the array identifier.

When you apply the sizeof operator to a structure or union type name, or to an identifier of structure or union type, the result is the number of bytes in the structure or union, including internal and trailing padding. This size may include internal and trailing padding used to align the members of the structure or union on memory boundaries. Thus, the result may not correspond to the size calculated by adding up the storage requirements of the individual members.

If an unsized array is the last element of a structure, the sizeof operator returns the size of the structure without the array.

buffer = calloc(100, sizeof (int) );

This example uses the sizeof operator to pass the size of an int, which varies among machines, as an argument to a run-time function named calloc. The value returned by the function is stored in buffer.

static char *strings[] ={
          "this is string one",
          "this is string two",
          "this is string three",
         };
const int string_no = ( sizeof strings ) / ( sizeof strings[0] );

In this example, strings is an array of pointers to char. The number of pointers is the number of elements in the array, but is not specified. It is easy to determine the number of pointers by using the sizeof operator to calculate the number of elements in the array. The const integer value string_no is initialized to this number. Because it is a const value, string_no cannot be modified.


Cast Operators

A type cast provides a method for explicit conversion of the type of an object in a specific situation.

Syntax

cast-expression :

unary-expression
( type-name ) cast-expression

The compiler treats cast-expression as type type-name after a type cast has been made. Casts can be used to convert objects of any scalar type to or from any other scalar type. Explicit type casts are constrained by the same rules that determine the effects of implicit conversions, discussed in Assignment Conversions. Additional restraints on casts may result from the actual sizes or representation of specific types. See Storage of Basic Types in Chapter 3 for information on actual sizes of integral types. For more information on type casts, see Type-Cast Conversions.


C Multiplicative Operators

The multiplicative operators perform multiplication (*), division (/), and remainder (%) operations.

Syntax

multiplicative-expression :

cast-expression
multiplicative-expression * cast-expression
multiplicative-expression / cast-expression
multiplicative-expression % cast-expression

The operands of the remainder operator (%) must be integral. The multiplication (*) and division (/) operators can take integral- or floating-type operands; the types of the operands can be different.

The multiplicative operators perform the usual arithmetic conversions on the operands. The type of the result is the type of the operands after conversion.

Note Since the conversions performed by the multiplicative operators do not provide for overflow or underflow conditions, information may be lost if the result of a multiplicative operation cannot be represented in the type of the operands after conversion.

The C multiplicative operators are described below:

Operator Description
* The multiplication operator causes its two operands to be multiplied.
/ The division operator causes the first operand to be divided by the second. If two integer operands are divided and the result is not an integer, it is truncated according to the following rules:
  • The result of division by 0 is undefined according to the ANSI C standard. The Microsoft C compiler generates an error at compile time or run time.
  • If both operands are positive or unsigned, the result is truncated toward 0.
  • If either operand is negative, whether the result of the operation is the largest integer less than or equal to the algebraic quotient or is the smallest integer greater than or equal to the algebraic quotient is implementation defined. (See the Microsoft Specific section below.)
% The result of the remainder operator is the remainder when the first operand is divided by the second. When the division is inexact, the result is determined by the following rules:
  • If the right operand is zero, the result is undefined.
  • If both operands are positive or unsigned, the result is positive.
  • If either operand is negative and the result is inexact, the result is implementation defined. (See the Microsoft Specific section below.)

Microsoft Specific —>

In division where either operand is negative, the direction of truncation is toward 0.

If either operation is negative in division with the remainder operator, the result has the same sign as the dividend (the first operand in the expression).

END Microsoft Specific

Examples

The declarations shown below are used for the following examples:

int i = 10, j = 3, n;
double x = 2.0, y;

This statement uses the multiplication operator:

y = x * i;

In this case, x is multiplied by i to give the value 20.0. The result has double type.

n = i / j;

In this example, 10 is divided by 3. The result is truncated toward 0, yielding the integer value 3.

n = i % j;

This statement assigns n the integer remainder, 1, when 10 is divided by 3.

Microsoft Specific —>

The sign of the remainder is the same as the sign of the dividend. For example:

50 % -6 = 2
-50 % 6 = -2

In each case, 50 and 2 have the same sign.

END Microsoft Specific


C Additive Operators

The additive operators perform addition (+) and subtraction (–).

Syntax

additive-expression :

multiplicative-expression
additive-expression + multiplicative-expression
additive-expression – multiplicative-expression

Note Although the syntax for additive-expression includes multiplicative-expression, this does not imply that expressions using multiplication are required. See the syntax in Appendix A, C Language Syntax Summary, for multiplicative-expression, cast-expression, and unary-expression.

The operands can be integral or floating values. Some additive operations can also be performed on pointer values, as outlined under the discussion of each operator.

The additive operators perform the usual arithmetic conversions on integral and floating operands. The type of the result is the type of the operands after conversion. Since the conversions performed by the additive operators do not provide for overflow or underflow conditions, information may be lost if the result of an additive operation cannot be represented in the type of the operands after conversion.


Addition (+)

The addition operator (+) causes its two operands to be added. Both operands can be either integral or floating types, or one operand can be a pointer and the other an integer.

When an integer is added to a pointer, the integer value (i) is converted by multiplying it by the size of the value that the pointer addresses. After conversion, the integer value represents i memory positions, where each position has the length specified by the pointer type. When the converted integer value is added to the pointer value, the result is a new pointer value representing the address i positions from the original address. The new pointer value addresses a value of the same type as the original pointer value and therefore is the same as array indexing (see One-Dimensional Arrays and Multidimensional Arrays). If the sum pointer points outside the array, except at the first location beyond the high end, the result is undefined. For more information, see Pointer Arithmetic.


Subtraction (-)

Subtraction (–)

The subtraction operator (–) subtracts the second operand from the first. Both operands can be either integral or floating types, or one operand can be a pointer and the other an integer.

When two pointers are subtracted, the difference is converted to a signed integral value by dividing the difference by the size of a value of the type that the pointers address. The size of the integral value is defined by the type ptrdiff_t in the standard include file STDDEF.H. The result represents the number of memory positions of that type between the two addresses. The result is only guaranteed to be meaningful for two elements of the same array, as discussed in Pointer Arithmetic.

When an integer value is subtracted from a pointer value, the subtraction operator converts the integer value (i) by multiplying it by the size of the value that the pointer addresses. After conversion, the integer value represents i memory positions, where each position has the length specified by the pointer type. When the converted integer value is subtracted from the pointer value, the result is the memory address i positions before the original address. The new pointer points to a value of the type addressed by the original pointer value.


Using the Additive Operators

The following examples, which illustrate the addition and subtraction operators, use these declarations:

int i = 4, j;
float x[10];
float *px;

These statements are equivalent:

px = &x[4 + i];
px = &x[4] + i;

The value of i is multiplied by the length of a float and added to &x[4]. The resulting pointer value is the address of x[8].

j = &x[i] - &x[i-2];

In this example, the address of the third element of x (given by x[i–2]) is subtracted from the address of the fifth element of x (given by x[i]). The difference is divided by the length of a float; the result is the integer value 2.


Pointer Arithmetic

Additive operations involving a pointer and an integer give meaningful results only if the pointer operand addresses an array member and the integer value produces an offset within the bounds of the same array. When the integer value is converted to an address offset, the compiler assumes that only memory positions of the same size lie between the original address and the address plus the offset.

This assumption is valid for array members. By definition, an array is a series of values of the same type; its elements reside in contiguous memory locations. However, storage for any types except array elements is not guaranteed to be filled by the same type of identifiers. That is, blanks can appear between memory positions, even positions of the same type. Therefore, the results of adding to or subtracting from the addresses of any values but array elements are undefined.

Similarly, when two pointer values are subtracted, the conversion assumes that only values of the same type, with no blanks, lie between the addresses given by the operands.


Bitwise Shift Operators

The shift operators shift their first operand left (<<) or right (>>) by the number of positions the second operand specifies.

Syntax

shift-expression :

additive-expression
shift-expression << additive-expression
shift-expression >> additive-expression

Both operands must be integral values. These operators perform the usual arithmetic conversions; the type of the result is the type of the left operand after conversion.

For leftward shifts, the vacated right bits are set to 0. For rightward shifts, the vacated left bits are filled based on the type of the first operand after conversion. If the type is unsigned, they are set to 0. Otherwise, they are filled with copies of the sign bit. For left-shift operators without overflow, the statement

expr1 << expr2

is equivalent to multiplication by 2expr2. For right-shift operators,

expr1 >> expr2

is equivalent to division by 2expr2 if expr1 is unsigned or has a nonnegative value.

The result of a shift operation is undefined if the second operand is negative, or if the right operand is greater than or equal to the width in bits of the promoted left operand.

Since the conversions performed by the shift operators do not provide for overflow or underflow conditions, information may be lost if the result of a shift operation cannot be represented in the type of the first operand after conversion.

unsigned int x, y, z;

x = 0x00AA;
y = 0x5500;

z = ( x << 8 ) + ( y >> 8 );

In this example, x is shifted left eight positions and y is shifted right eight positions. The shifted values are added, giving 0xAA55, and assigned to z.

Shifting a negative value to the right yields half the absolute value, rounded down. For example, –253 (binary 11111111 00000011) shifted right one bit produces –127 (binary 11111111 10000001). A positive 253 shifts right to produce +126.

Right shifts preserve the sign bit. When a signed integer shifts right, the most-significant bit remains set. When an unsigned integer shifts right, the most-significant bit is cleared.

If 0xF000 is unsigned, the result is 0x7800. If 0xF0000000 is signed, a right shift produces 0xF8000000. Shifting a positive number right 32 times produces 0xF0000000. Shifting a negative number right 32 times produces 0xFFFFFFFF.


C Relational and Equality Operators

The binary relational and equality operators compare their first operand to their second operand to test the validity of the specified relationship. The result of a relational expression is 1 if the tested relationship is true and 0 if it is false. The type of the result is int.

Syntax

relational-expression :

shift-expression
relational-expression < shift-expression
relational-expression > shift-expression
relational-expression <= shift-expression
relational-expression >= shift-expression

equality-expression :

relational-expression
equality-expression == relational-expression
equality-expression != relational-expression

The relational and equality operators test the following relationships:

Operator | Relationship Tested
< | First operand less than second operand
> | First operand greater than second operand
<= | First operand less than or equal to second operand
>= | First operand greater than or equal to second operand
== | First operand equal to second operand
!= | First operand not equal to second operand

The first four operators in the list above have a higher precedence than the equality operators (== and !=). See the precedence information in Table 4.1.

The operands can have integral, floating, or pointer type. The types of the operands can be different. Relational operators perform the usual arithmetic conversions on integral and floating type operands. In addition, you can use the following combinations of operand types with the relational and equality operators:

  • Both operands of any relational or equality operator can be pointers to the same type. For the equality (==) and inequality (!=) operators, the result of the comparison indicates whether the two pointers address the same memory location. For the other relational operators (<, >, <=, and >=), the result of the comparison indicates the relative position of the two memory addresses of the objects pointed to. Relational operators compare only offsets.

    Pointer comparison is defined only for parts of the same object. If the pointers refer to members of an array, the comparison is equivalent to comparison of the corresponding subscripts. The address of the first array element is “less than” the address of the last element. In the case of structures, pointers to structure members declared later are “greater than” pointers to members declared earlier in the structure. Pointers to the members of the same union are equal.

  • A pointer value can be compared to the constant value 0 for equality (==) or inequality (!=). A pointer with a value of 0 is called a “null” pointer; that is, it does not point to a valid memory location.

  • The equality operators follow the same rules as the relational operators, but permit additional possibilities: a pointer can be compared to a constant integral expression with value 0, or to a pointer to void. If two pointers are both null pointers, they compare as equal. Equality operators compare both segment and offset.

Examples

The examples below illustrate relational and equality operators.

int x = 0, y = 0;
if ( x < y )

Because x and y are equal, the expression in this example yields the value 0.

char array[10];
char *p;

for ( p = array; p < &array[10]; p++ )
    *p = '\0';

The fragment in this example sets each element of array to a null character constant.

enum color { red, white, green } col;
   .
   .
   .
   if ( col == red )
   .
   .
   .

These statements declare an enumeration variable named col with the tag color. At any time, the variable may contain an integer value of 0, 1, or 2, which represents one of the elements of the enumeration set color: the color red, white, or green, respectively. If col contains 0 when the if statement is executed, any statements depending on the if will be executed.


C Bitwise Operators

The bitwise operators perform bitwise-AND (&), bitwise-exclusive-OR (^), and bitwise-inclusive-OR (|) operations.

Syntax

AND-expression :

equality-expression
AND-expression & equality-expression

exclusive-OR-expression :

AND-expression
exclusive-OR-expression ^ AND-expression

inclusive-OR-expression :

exclusive-OR-expression
inclusive-OR-expression | exclusive-OR-expression

The operands of bitwise operators must have integral types, but their types can be different. These operators perform the usual arithmetic conversions; the type of the result is the type of the operands after conversion.

The C bitwise operators are described below:

Operator | Description
& | The bitwise-AND operator compares each bit of its first operand to the corresponding bit of its second operand. If both bits are 1, the corresponding result bit is set to 1. Otherwise, the corresponding result bit is set to 0.
^ | The bitwise-exclusive-OR operator compares each bit of its first operand to the corresponding bit of its second operand. If one bit is 0 and the other bit is 1, the corresponding result bit is set to 1. Otherwise, the corresponding result bit is set to 0.
| | The bitwise-inclusive-OR operator compares each bit of its first operand to the corresponding bit of its second operand. If either bit is 1, the corresponding result bit is set to 1. Otherwise, the corresponding result bit is set to 0.

Examples

These declarations are used for the following three examples:

short i = 0xAB00;
short j = 0xABCD;
short n;

n = i & j;

The result assigned to n in this first example is the same as i (0xAB00 hexadecimal).

n = i | j;

n = i ^ j;

The bitwise-inclusive OR in the second example results in the value 0xABCD (hexadecimal), while the bitwise-exclusive OR in the third example produces 0xCD (hexadecimal).

Microsoft Specific —>

The results of bitwise operation on signed integers is implementation-defined according to the ANSI C standard. For the Microsoft C compiler, bitwise operations on signed integers work the same as bitwise operations on unsigned integers. For example, -16 & 99 can be expressed in binary as

  11111111 11110000
& 00000000 01100011
  _________________
  00000000 01100000

The result of the bitwise AND is 96 decimal.

END Microsoft Specific


C Logical Operators

The logical operators perform logical-AND (&&) and logical-OR ( || ) operations.

Syntax

logical-AND-expression :

inclusive-OR-expression
logical-AND-expression && inclusive-OR-expression

logical-OR-expression :

logical-AND-expression
logical-OR-expression || logical-AND-expression

Logical operators do not perform the usual arithmetic conversions. Instead, they evaluate each operand in terms of its equivalence to 0. The result of a logical operation is either 0 or 1. The result’s type is int.

The C logical operators are described below:

Operator | Description
&& | The logical-AND operator produces the value 1 if both operands have nonzero values. If either operand is equal to 0, the result is 0. If the first operand of a logical-AND operation is equal to 0, the second operand is not evaluated.
|| | The logical-OR operator performs an inclusive-OR operation on its operands. The result is 0 if both operands have 0 values. If either operand has a nonzero value, the result is 1. If the first operand of a logical-OR operation has a nonzero value, the second operand is not evaluated.

The operands of logical-AND and logical-OR expressions are evaluated from left to right. If the value of the first operand is sufficient to determine the result of the operation, the second operand is not evaluated. This is called “short-circuit evaluation.” There is a sequence point after the first operand. See Sequence Points for more information.

Examples

The following examples illustrate the logical operators:

int w, x, y, z;

if ( x < y && y < z )
    printf( "x is less than z\n" );

In this example, the printf function is called to print a message if x is less than y and y is less than z. If x is greater than y, the second operand (y < z) is not evaluated and nothing is printed. Note that this could cause problems in cases where the second operand has side effects that are being relied on for some other reason.

printf( "%d" , (x == w || x == y || x == z) );

In this example, if x is equal to either w, y, or z, the second argument to the printf function evaluates to true and the value 1 is printed. Otherwise, it evaluates to false and the value 0 is printed. As soon as one of the conditions evaluates to true, evaluation ceases.


Conditional-Expression Operator

C has one ternary operator: the conditional-expression operator (? :).

Syntax

conditional-expression :

logical-OR-expression
logical-OR-expression ? expression : conditional-expression

The logical-OR-expression must have integral, floating, or pointer type. It is evaluated in terms of its equivalence to 0. A sequence point follows logical-OR-expression. Evaluation of the operands proceeds as follows:

  • If logical-OR-expression is not equal to 0, expression is evaluated. The result of evaluating the expression is given by the nonterminal expression. (This means expression is evaluated only if logical-OR-expression is true.)

  • If logical-OR-expression equals 0, conditional-expression is evaluated. The result of the expression is the value of conditional-expression. (This means conditional-expression is evaluated only if logical-OR-expression is false.)

Note that either expression or conditional-expression is evaluated, but not both.

The type of the result of a conditional operation depends on the type of the expression or conditional-expression operand, as follows:

  • If expression or conditional-expression has integral or floating type (their types can be different), the operator performs the usual arithmetic conversions. The type of the result is the type of the operands after conversion.

  • If both expression and conditional-expression have the same structure, union, or pointer type, the type of the result is the same structure, union, or pointer type.

  • If both operands have type void, the result has type void.

  • If either operand is a pointer to an object of any type, and the other operand is a pointer to void, the pointer to the object is converted to a pointer to void and the result is a pointer to void.

  • If either expression or conditional-expression is a pointer and the other operand is a constant expression with the value 0, the type of the result is the pointer type.

In the type comparison for pointers, any type qualifiers (const or volatile) in the type to which the pointer points are insignificant, but the result type inherits the qualifiers from both components of the conditional.

Examples

The following examples show uses of the conditional operator:

j = ( i < 0 ) ? ( -i ) : ( i );

This example assigns the absolute value of i to j. If i is less than 0, -i is assigned to j. If i is greater than or equal to 0, i is assigned to j.

void f1( void );
void f2( void );
int x;
int y;
    .
    .
    .
( x == y ) ? ( f1() ) : ( f2() );

In this example, two functions, f1 and f2, and two variables, x and y, are declared. Later in the program, if the two variables have the same value, the function f1 is called. Otherwise, f2 is called.


C Assignment Operators

An assignment operation assigns the value of the right-hand operand to the storage location named by the left-hand operand. Therefore, the left-hand operand of an assignment operation must be a modifiable l-value. After the assignment, an assignment expression has the value of the left operand but is not an l-value.

Syntax

assignment-expression :

conditional-expression
unary-expression assignment-operator assignment-expression

assignment-operator : one of

= *= /= %= += –= <<= >>= &= ^= |=

The assignment operators in C can both transform and assign values in a single operation. C provides the following assignment operators:

Operator | Operation Performed
= | Simple assignment
*= | Multiplication assignment
/= | Division assignment
%= | Remainder assignment
+= | Addition assignment
–= | Subtraction assignment
<<= | Left-shift assignment
>>= | Right-shift assignment
&= | Bitwise-AND assignment
^= | Bitwise-exclusive-OR assignment
|= | Bitwise-inclusive-OR assignment

In assignment, the type of the right-hand value is converted to the type of the left-hand value, and the value is stored in the left operand after the assignment has taken place. The left operand must not be an array, a function, or a constant. The specific conversion path, which depends on the two types, is outlined in detail in Type Conversions.


Simple Assignment

The simple-assignment operator assigns its right operand to its left operand. The value of the right operand is converted to the type of the assignment expression and replaces the value stored in the object designated by the left operand. The conversion rules for assignment apply (see Assignment Conversions).

double x;
int y;

x = y;

In this example, the value of y is converted to type double and assigned to x.


C Compound Assignment

The compound-assignment operators combine the simple-assignment operator with another binary operator. Compound-assignment operators perform the operation specified by the additional operator, then assign the result to the left operand. For example, a compound-assignment expression such as

expression1 += expression2

can be understood as

expression1 = expression1 + expression2

However, the compound-assignment expression is not equivalent to the expanded version because the compound-assignment expression evaluates expression1 only once, while the expanded version evaluates expression1 twice: in the addition operation and in the assignment operation.

The operands of a compound-assignment operator must be of integral or floating type. Each compound-assignment operator performs the conversions that the corresponding binary operator performs and restricts the types of its operands accordingly. The addition-assignment (+=) and subtraction-assignment (–=) operators can also have a left operand of pointer type, in which case the right-hand operand must be of integral type. The result of a compound-assignment operation has the value and type of the left operand.

#define MASK 0xff00

n &= MASK;

In this example, a bitwise-inclusive-AND operation is performed on n and MASK, and the result is assigned to n. The manifest constant MASK is defined with a #define preprocessor directive.


Sequential-Evaluation Operator

The sequential-evaluation operator, also called the “comma operator,” evaluates its two operands sequentially from left to right.

Syntax

expression :

assignment-expression
expression , assignment-expression

The left operand of the sequential-evaluation operator is evaluated as a void expression. The result of the operation has the same value and type as the right operand. Each operand can be of any type. The sequential-evaluation operator does not perform type conversions between its operands, and it does not yield an l-value. There is a sequence point after the first operand, which means all side effects from the evaluation of the left operand are completed before beginning evaluation of the right operand. See Sequence Points for more information.

The sequential-evaluation operator is typically used to evaluate two or more expressions in contexts where only one expression is allowed.

Commas can be used as separators in some contexts. However, you must be careful not to confuse the use of the comma as a separator with its use as an operator; the two uses are completely different.

Example

This example illustrates the sequential-evaluation operator:

for ( i = j = 1; i + j < 20; i += i, j-- );

In this example, each operand of the for statement’s third expression is evaluated independently. The left operand i += i is evaluated first; then the right operand, j––, is evaluated.

func_one( x, y + 2, z );
func_two( (x--, y + 2), z );

In the function call to func_one, three arguments, separated by commas, are passed: x, y + 2, and z. In the function call to func_two, parentheses force the compiler to interpret the first comma as the sequential-evaluation operator. This function call passes two arguments to func_two. The first argument is the result of the sequential-evaluation operation (x--, y + 2), which has the value and type of the expression y + 2; the second argument is z.


Type Conversions

Type conversions depend on the specified operator and the type of the operand or operators. Type conversions are performed in the following cases:

  • When a value of one type is assigned to a variable of a different type or an operator converts the type of its operand or operands before performing an operation

  • When a value of one type is explicitly cast to a different type

  • When a value is passed as an argument to a function or when a type is returned from a function

A character, a short integer, or an integer bit field, all either signed or not, or an object of enumeration type, can be used in an expression wherever an integer can be used. If an int can represent all the values of the original type, then the value is converted to int; otherwise, it is converted to unsigned int. This process is called “integral promotion.” Integral promotions preserve value. That is, the value after promotion is guaranteed to be the same as before the promotion. See Usual Arithmetic Conversions for more information.


Assignment Conversions

In assignment operations, the type of the value being assigned is converted to the type of the variable that receives the assignment. C allows conversions by assignment between integral and floating types, even if information is lost in the conversion. The conversion method used depends on the types involved in the assignment, as described in Usual Arithmetic Conversions and in the following sections:

  • Conversions from Signed Integral Types

  • Conversions from Unsigned Integral Types

  • Conversions from Floating-Point Types

  • Conversions to and from Pointer Types

  • Conversions from Other Types

Type qualifiers do not affect the allowability of the conversion although a const l-value cannot be used on the left side of the assignment.


Conversions from Signed Integral Types

When a signed integer is converted to an unsigned integer with equal or greater size and the value of the signed integer is not negative, the value is unchanged. The conversion is made by sign-extending the signed integer. A signed integer is converted to a shorter signed integer by truncating the high-order bits. The result is interpreted as an unsigned value, as shown in this example.

int i = -3;
unsigned short u;

u = i;
printf( "%hu\n", u );  /* Prints 65533 */

No information is lost when a signed integer is converted to a floating value, except that some precision may be lost when a long int or unsigned long int value is converted to a float value.

Table 4.2 summarizes conversions from signed integral types. This table assumes that the char type is signed by default. If you use a compile-time option to change the default for the char type to unsigned, the conversions given in Table 4.3 for the unsigned char type apply instead of the conversions in Table 4.2.

Table 4.2 Conversions from Signed Integral Types

From | To | Method
char1 | short | Sign-extend
char | long | Sign-extend
char | unsigned char | Preserve pattern; high-order bit loses function as sign bit
char | unsigned short | Sign-extend to short; convert short to unsigned short
char | unsigned long | Sign-extend to long; convert long to unsigned long
char | float | Sign-extend to long; convert long to float
char | double | Sign-extend to long; convert long to double
char | long double | Sign-extend to long; convert long to double
short | char | Preserve low-order byte
short | long | Sign-extend
short | unsigned char | Preserve low-order byte
short | unsigned short | Preserve bit pattern; high-order bit loses function as sign bit
short | unsigned long | Sign-extend to long; convert long to unsigned long
short | float | Sign-extend to long; convert long to float
short | double | Sign-extend to long; convert long to double
short | long double | Sign-extend to long; convert long to double
long | char | Preserve low-order byte
long | short | Preserve low-order word
long | unsigned char | Preserve low-order byte
long | unsigned short | Preserve low-order word
long | unsigned long | Preserve bit pattern; high-order bit loses function as sign bit
long | float | Represent as float. If long cannot be represented exactly, some precision is lost.
long | double | Represent as double. If long cannot be represented exactly as a double, some precision is lost.
long | long double | Represent as double. If long cannot be represented exactly as a double, some precision is lost.

1. All char entries assume that the char type is signed by default.

Microsoft Specific —>

For the Microsoft 32-bit C compiler, an integer is equivalent to a long. Conversion of an int value proceeds the same as for a long.

END Microsoft Specific


Conversions from Unsigned Integral Types

An unsigned integer is converted to a shorter unsigned or signed integer by truncating the high-order bits, or to a longer unsigned or signed integer by zero-extending (see Table 4.3).

When the value with integral type is demoted to a signed integer with smaller size, or an unsigned integer is converted to its corresponding signed integer, the value is unchanged if it can be represented in the new type. However, the value it represents changes if the sign bit is set, as in the following example.

int j;
unsigned short k = 65533;

j = k;
printf( "%hd\n", j );   /* Prints -3 */

If it cannot be represented, the result is implementation-defined. See Type-Cast Conversions for information on the Microsoft C compiler’s handling of demotion of integers. The same behavior results from integer conversion or from type casting the integer.

Unsigned values are converted in a way that preserves their value and is not representable directly in C. The only exception is a conversion from unsigned long to float, which loses at most the low-order bits. Otherwise, value is preserved, signed or unsigned. When a value of integral type is converted to floating, and the value is outside the range representable, the result is undefined. (See Storage of Basic Types in Chapter 3 for information about the range for integral and floating-point types.)

Table 4.3 summarizes conversions from unsigned integral types.

Table 4.3 Conversions from Unsigned Integral Types

From | To | Method
unsigned char | char | Preserve bit pattern; high-order bit becomes sign bit
unsigned char | short | Zero-extend
unsigned char | long | Zero-extend
unsigned char | unsigned short | Zero-extend
unsigned char | unsigned long | Zero-extend
unsigned char | float | Convert to long; convert long to float
unsigned char | double | Convert to long; convert long to double
unsigned char | long double | Convert to long; convert long to double
unsigned short | char | Preserve low-order byte
unsigned short | short | Preserve bit pattern; high-order bit becomes sign bit
unsigned short | long | Zero-extend
unsigned short | unsigned char | Preserve low-order byte
unsigned short | unsigned long | Zero-extend
unsigned short | float | Convert to long; convert long to float
unsigned short | double | Convert to long; convert long to double
unsigned short | long double | Convert to long; convert long to double
unsigned long | char | Preserve low-order byte
unsigned long | short | Preserve low-order word
unsigned long | long | Preserve bit pattern; high-order bit becomes sign bit
unsigned long | unsigned char | Preserve low-order byte
unsigned long | unsigned short | Preserve low-order word
unsigned long | float | Convert to long; convert long to float
unsigned long | double | Convert directly to double
unsigned long | long double | Convert to long; convert long to double

Microsoft Specific —>

For the Microsoft 32-bit C compiler, the unsigned int type is equivalent to the unsigned long type. Conversion of an unsigned int value proceeds in the same way as conversion of an unsigned long. Conversions from unsigned long values to float are not accurate if the value being converted is larger than the maximum positive signed long value.

END Microsoft Specific


Conversions from Floating-Point Types

A float value converted to a double or long double, or a double converted to a long double, undergoes no change in value. A double value converted to a float value is represented exactly, if possible. Precision may be lost if the value cannot be represented exactly. If the result is out of range, the behavior is undefined. See Limits on Floating-Point Constants in Chapter 1 for the range of floating-point types.

A floating value is converted to an integral value by first converting to a long, then from the long value to the specific integral value, as described below in Table 4.4. The decimal portion of the floating value is discarded in the conversion to a long. If the result is still too large to fit into a long, the result of the conversion is undefined.

Microsoft Specific —>

When converting a double or long double floating-point number to a smaller floating-point number, the value of the floating-point variable is truncated toward zero when an underflow occurs. An overflow causes a run-time error. Note that the Microsoft C compiler maps long double to type double.

END Microsoft Specific

Table 4.4 summarizes conversions from floating types.

Table 4.4 Conversions from Floating-Point Types

From | To | Method
float | char | Convert to long; convert long to char
float | short | Convert to long; convert long to short
float | long | Truncate at decimal point. If result is too large to be represented as long, result is undefined.
float | unsigned short | Convert to long; convert long to unsigned short
float | unsigned long | Convert to long; convert long to unsigned long
float | double | Change internal representation
float | long double | Change internal representation
double | char | Convert to float; convert float to char
double | short | Convert to float; convert float to short
double | long | Truncate at decimal point. If result is too large to be represented as long, result is undefined.
double | unsigned short | Convert to long; convert long to unsigned short
double | unsigned long | Convert to long; convert long to unsigned long
double | float | Represent as a float. If double value cannot be represented exactly as float, loss of precision occurs. If value is too large to be represented as float, the result is undefined.
long double | char | Convert to float; convert float to char
long double | short | Convert to float; convert float to short
long double | long | Truncate at decimal point. If result is too large to be represented as long, result is undefined.
long double | unsigned short | Convert to long; convert long to unsigned short
long double | unsigned long | Convert to long; convert long to unsigned long
long double | float | Represent as a float. If double value cannot be represented exactly as float, loss of precision occurs. If value is too large to be represented as float, the result is undefined.
long double | double | The long double value is treated as double.

Conversions from float, double, or long double values to unsigned long are not accurate if the value being converted is larger than the maximum positive long value.


Conversions to and from Pointer Types

A pointer to one type of value can be converted to a pointer to a different type. However, the result may be undefined because of the alignment requirements and sizes of different types in storage. A pointer to an object can be converted to a pointer to an object whose type requires less or equally strict storage alignment, and back again without change.

A pointer to void can be converted to or from a pointer to any type, without restriction or loss of information. If the result is converted back to the original type, the original pointer is recovered.

If a pointer is converted to another pointer with the same type but having different or additional qualifiers, the new pointer is the same as the old except for restrictions imposed by the new qualifier.

A pointer value can also be converted to an integral value. The conversion path depends on the size of the pointer and the size of the integral type, according to the following rules:

  • If the size of the pointer is greater than or equal to the size of the integral type, the pointer behaves like an unsigned value in the conversion, except that it cannot be converted to a floating value.

  • If the pointer is smaller than the integral type, the pointer is first converted to a pointer with the same size as the integral type, then converted to the integral type.

Conversely, an integral type can be converted to a pointer type according to the following rules:

  • If the integral type is the same size as the pointer type, the conversion simply causes the integral value to be treated as a pointer (an unsigned integer).

  • If the size of the integral type is different from the size of the pointer type, the integral type is first converted to the size of the pointer, using the conversion paths given in Table 4.2 and Table 4.3. It is then treated as a pointer value.

An integral constant expression with value 0 or such an expression cast to type void * can be converted by a type cast, by assignment, or by comparison to a pointer of any type. This produces a null pointer that is equal to another null pointer of the same type, but this null pointer is not equal to any pointer to a function or to an object. Integers other than the constant 0 can be converted to pointer type, but the result is not portable.


Conversions from Other Types

Since an enum value is an int value by definition, conversions to and from an enum value are the same as those for the int type. For the Microsoft C compiler, an integer is the same as a long.

Microsoft Specific —>

No conversions between structure or union types are allowed.

Any value can be converted to type void, but the result of such a conversion can be used only in a context where an expression value is discarded, such as in an expression statement.

The void type has no value, by definition. Therefore, it cannot be converted to any other type, and other types cannot be converted to void by assignment. However, you can explicitly cast a value to type void, as discussed in Type-Cast Conversions.

END Microsoft Specific


Type-Cast Conversions

You can use type casts to explicitly convert types.

Syntax

cast-expression :

unary expression
( type-name ) cast-expression

type-name :

specifier-qualifier-list abstract-declarator opt

The type-name is a type and cast-expression is a value to be converted to that type. An expression with a type cast is not an l-value. The cast-expression is converted as though it had been assigned to a variable of type type-name. The conversion rules for assignments (outlined in Assignment Conversions) apply to type casts as well. Table 4.5 shows the types that can be cast to any given type.

Table 4.5 Legal Type Casts

Destination Types | Potential Sources
Integral types | Any integer type or floating-point type, or pointer to an object
Floating-point | Any arithmetic type
A pointer to an object, or (void *) | Any integer type, (void *), a pointer to an object, or a function pointer
Function pointer | Any integral type, a pointer to an object, or a function pointer
A structure, union, or array | None
Void type | Any type

Any identifier can be cast to void type. However, if the type specified in a type-cast expression is not void, then the identifier being cast to that type cannot be a void expression. Any expression can be cast to void, but an expression of type void cannot be cast to any other type. For example, a function with void return type cannot have its return cast to another type.

Note that a void * expression has a type pointer to void, not type void. If an object is cast to void type, the resulting expression cannot be assigned to any item. Similarly, a type-cast object is not an acceptable l-value, so no assignment can be made to a type-cast object.

Microsoft Specific —>

A type cast can be an l-value expression as long as the size of the identifier does not change. For information on l-value expressions, see L-Value and R-Value Expressions.

END Microsoft Specific

You can convert an expression to type void with a cast, but the resulting expression can be used only where a value is not required. An object pointer converted to void * and back to the original type will return to its original value.


Function-Call Conversions

The type of conversion performed on the arguments in a function call depends on the presence of a function prototype (forward declaration) with declared argument types for the called function.

If a function prototype is present and includes declared argument types, the compiler performs type checking (see Chapter 6, Functions).

If no function prototype is present, only the usual arithmetic conversions are performed on the arguments in the function call. These conversions are performed independently on each argument in the call. This means that a float value is converted to a double; a char or short value is converted to an int; and an unsigned char or unsigned short is converted to an unsigned int.


Statements

The statements of a C program control the flow of program execution. In C, as in other programming languages, several kinds of statements are available to perform loops, to select other statements to be executed, and to transfer control. Following a brief overview of statement syntax, this chapter describes the C statements in alphabetical order:

break statement | if statement
compound statement | null statement
continue statement | return statement
do-while statement | switch statement
expression statement | try-except statement
for statement | try-finally statement
goto and labeled statements | while statement


Overview of C Statements

C statements consist of tokens, expressions, and other statements. A statement that forms a component of another statement is called the “body” of the enclosing statement. Each statement type given by the following syntax is discussed in this chapter.

Syntax

statement :

labeled-statement
compound-statement
expression-statement
selection-statement
iteration-statement
jump-statement
try-except-statement /* Microsoft Specific */
try-finally-statement /* Microsoft Specific */

Frequently the statement body is a “compound statement.” A compound statement consists of other statements that can include keywords. The compound statement is delimited by braces ({ }). All other C statements end with a semicolon (;). The semicolon is a statement terminator.

The expression statement contains a C expression that can contain the arithmetic or logical operators introduced in Chapter 4, Expressions and Assignments. The null statement is an empty statement.

Any C statement can begin with an identifying label consisting of a name and a colon. Since only the goto statement recognizes statement labels, statement labels are discussed with goto. See The goto and Labeled Statements for more information.


The C break Statement

The break statement terminates the execution of the nearest enclosing do, for, switch, or while statement in which it appears. Control passes to the statement that follows the terminated statement.

Syntax

jump-statement :

break;

The break statement is frequently used to terminate the processing of a particular case within a switch statement. Lack of an enclosing iterative or switch statement generates an error.

Within nested statements, the break statement terminates only the do, for, switch, or while statement that immediately encloses it. You can use a return or goto statement to transfer control elsewhere out of the nested structure.

This example illustrates the break statement:

for ( i = 0; i < LENGTH; i++ )  /* Execution returns here when */
{                               /* break statement is executed */
    for ( j = 0; j < WIDTH; j++)
    {
        if ( lines[i][j] == '\0' )
        {
            lengths[i] = j;
            break;
        }
    }
}

The example processes an array of variable-length strings stored in lines. The break statement causes an exit from the interior for loop after the terminating null character ('\0') of each string is found and its position is stored in lengths[i].

The variable j is not incremented when break causes the exit from the interior loop. Control then returns to the outer for loop. The variable i is incremented and the process is repeated until i is greater than or equal to LENGTH.


The Compound Statement

A compound statement (also called a “block”) typically appears as the body of another statement, such as the if statement. Chapter 3, Declarations and Types, describes the form and meaning of the declarations that can appear at the head of a compound statement.

Syntax

compound-statement :

{ declaration-list opt statement-list opt }

declaration-list :

declaration
declaration-list declaration

statement-list :

statement
statement-list statement

If there are declarations, they must come before any statements. The scope of each identifier declared at the beginning of a compound statement extends from its declaration point to the end of the block. It is visible throughout the block unless a declaration of the same identifier exists in an inner block.

Identifiers in a compound statement are presumed auto unless explicitly declared otherwise with register, static, or extern, except functions, which can only be extern. You can leave off the extern specifier in function declarations and the function will still be extern.

Storage is not allocated and initialization is not permitted if a variable or function is declared in a compound statement with storage class extern. The declaration refers to an external variable or function defined elsewhere.

Variables declared in a block with the auto or register keyword are reallocated and, if necessary, initialized each time the compound statement is entered. These variables are not defined after the compound statement is exited. If a variable declared inside a block has the static attribute, the variable is initialized when program execution begins and keeps its value throughout the program. See Storage Classes in Chapter 3 for information about static.

This example illustrates a compound statement:

if ( i > 0 )
{
    line[i] = x;
    x++;
    i--;
}

In this example, if i is greater than 0, all statements inside the compound statement are executed in order.


The C continue Statement

The continue statement passes control to the next iteration of the do, for, or while statement in which it appears, bypassing any remaining statements in the do, for, or while statement body. A typical use of the continue statement is to return to the start of a loop from within a deeply nested loop.

Syntax

jump-statement :

continue;

The next iteration of a do, for, or while statement is determined as follows:

  • Within a do or a while statement, the next iteration starts by reevaluating the expression of the do or while statement.

  • A continue statement in a for statement causes the first expression of the for statement to be evaluated. Then the compiler reevaluates the conditional expression and, depending on the result, either terminates or iterates the statement body. See The for Statement for more information on the for statement and its nonterminals.

This is an example of the continue statement:

while ( i-- > 0 )
{
    x = f( i );
    if ( x == 1 )
        continue;
    y += x * x;
}

In this example, the statement body is executed while i is greater than 0. First f(i) is assigned to x; then, if x is equal to 1, the continue statement is executed. The rest of the statements in the body are ignored, and execution resumes at the top of the loop with the evaluation of the loop’s test.


The do-while Statement

The do-while statement lets you repeat a statement or compound statement until a specified expression becomes false.

Syntax

iteration-statement :

do statement while ( expression ) ;

The expression in a do-while statement is evaluated after the body of the loop is executed. Therefore, the body of the loop is always executed at least once.

The expression must have arithmetic or pointer type. Execution proceeds as follows:

  1. The statement body is executed.

  2. Next, expression is evaluated. If expression is false, the do-while statement terminates and control passes to the next statement in the program. If expression is true (nonzero), the process is repeated, beginning with step 1.

The do-while statement can also terminate when a break, goto, or return statement is executed within the statement body.

This is an example of the do-while statement:

do
{
    y = f( x );
    x--;
} while ( x > 0 );

In this do-while statement, the two statements y = f( x ); and x--; are executed, regardless of the initial value of x. Then x > 0 is evaluated. If x is greater than 0, the statement body is executed again and x > 0 is reevaluated. The statement body is executed repeatedly as long as x remains greater than 0. Execution of the do-while statement terminates when x becomes 0 or negative. The body of the loop is executed at least once.


The Expression Statement

When an expression statement is executed, the expression is evaluated according to the rules outlined in Chapter 4, Expressions and Assignments.

Syntax

expression-statement :

expression opt ;

All side effects from the expression evaluation are completed before the next statement is executed. An empty expression statement is called a null statement. See The Null Statement for more information.

These examples demonstrate expression statements.

x = ( y + 3 );            /* x is assigned the value of y + 3  */
x++;                      /* x is incremented                  */
x = y = 0;                /* Both x and y are initialized to 0 */
proc( arg1, arg2 );       /* Function call returning void      */
y = z = ( f( x ) + 3 );   /* A function-call expression        */

In the last statement, the function-call expression, the value of the expression, which includes any value returned by the function, is increased by 3 and then assigned to both the variables y and z.


The C for Statement

The for statement lets you repeat a statement or compound statement a specified number of times. The body of a for statement is executed zero or more times until an optional condition becomes false. You can use optional expressions within the for statement to initialize and change values during the for statement’s execution.

Syntax

iteration-statement :

for ( init-expression opt ; cond-expression opt ; loop-expression opt ) statement

Execution of a for statement proceeds as follows:

  1. The init-expression, if any, is evaluated. This specifies the initialization for the loop. There is no restriction on the type of init-expression.

  2. The cond-expression, if any, is evaluated. This expression must have arithmetic or pointer type. It is evaluated before each iteration. Three results are possible:
    • If cond-expression is true (nonzero), statement is executed; then loop-expression, if any, is evaluated. The loop-expression is evaluated after each iteration. There is no restriction on its type. Side effects will execute in order. The process then begins again with the evaluation of cond-expression.

    • If cond-expression is omitted, cond-expression is considered true, and execution proceeds exactly as described in the previous paragraph. A for statement without a cond-expression argument terminates only when a break or return statement within the statement body is executed, or when a goto (to a labeled statement outside the for statement body) is executed.

    • If cond-expression is false (0), execution of the for statement terminates and control passes to the next statement in the program.

A for statement also terminates when a break, goto, or return statement within the statement body is executed. A continue statement in a for loop causes loop-expression to be evaluated. When a break statement is executed inside a for loop, loop-expression is not evaluated or executed. This statement

for( ;; );

is the customary way to produce an infinite loop which can only be exited with a break, goto, or return statement.

This example illustrates the for statement:

for ( i = space = tab = 0; i < MAX; i++ )
{
    if ( line[i] == ' ' )
        space++;
    if ( line[i] == '\t' )
    {
        tab++;
        line[i] = ' ';
    }
}

This example counts space (' ') and tab ('\t') characters in the array of characters named line and replaces each tab character with a space. First i, space, and tab are initialized to 0. Then i is compared with the constant MAX; if i is less than MAX, the statement body is executed. Depending on the value of line[i], the body of one or neither of the if statements is executed. Then i is incremented and tested against MAX; the statement body is executed repeatedly as long as i is less than MAX.


The goto and Labeled Statements

The goto statement transfers control to a label. The given label must reside in the same function and can appear before only one statement in the same function.

Syntax

statement :

labeled-statement
jump-statement

jump-statement :

goto identifier ;

labeled-statement :

identifier : statement

A statement label is meaningful only to a goto statement; in any other context, a labeled statement is executed without regard to the label.

A jump-statement must reside in the same function and can appear before only one statement in the same function. The set of identifier names following a goto has its own name space so the names do not interfere with other identifiers. Labels cannot be redeclared. See Name Spaces for more information.

It is good programming style to use the break, continue, and return statement in preference to goto whenever possible. Since the break statement only exits from one level of the loop, a goto may be necessary for exiting a loop from within a deeply nested loop.

This example demonstrates the goto statement:

void main()
{
    int i, j;

    for ( i = 0; i < 10; i++ )
    {
        printf( "Outer loop executing. i = %d\n", i );
        for ( j = 0; j < 3; j++ )
        {
            printf( " Inner loop executing. j = %d\n", j );
            if ( i == 5 )
                goto stop;
        }
    }
    /* This message does not print: */
    printf( "Loop exited. i = %d\n", i );
    stop: printf( "Jumped to stop. i = %d\n", i );
}

In this example, a goto statement transfers control to the point labeled stop when i equals 5.


The C if Statement

The if statement controls conditional branching. The body of an if statement is executed if the value of the expression is nonzero. The syntax for the if statement has two forms.

Syntax

selection-statement :

if ( expression ) statement
if ( expression ) statement else statement

In both forms of the if statement, the expressions, which can have any value except a structure, are evaluated, including all side effects.

In the first form of the syntax, if expression is true (nonzero), statement is executed. If expression is false, statement is ignored. In the second form of syntax, which uses else, the second statement is executed if expression is false. With both forms, control then passes from the if statement to the next statement in the program unless one of the statements contains a break, continue, or goto.

The following are examples of the if statement:

if ( i > 0 )
    y = x / i;
else
{
    x = i;
    y = f( x );
}

In this example, the statement y = x/i; is executed if i is greater than 0. If i is less than or equal to 0, i is assigned to x and f( x ) is assigned to y. Note that the statement forming the if clause ends with a semicolon.

When nesting if statements and else clauses, use braces to group the statements and clauses into compound statements that clarify your intent. If no braces are present, the compiler resolves ambiguities by associating each else with the closest if that lacks an else.

if ( i > 0 )           /* Without braces */
    if ( j > i )
        x = j;
    else
        x = i;

The else clause is associated with the inner if statement in this example. If i is less than or equal to 0, no value is assigned to x.

if ( i > 0 )
{                      /* With braces */
    if ( j > i )
        x = j;
}
else
    x = i;

The braces surrounding the inner if statement in this example make the else clause part of the outer if statement. If i is less than or equal to 0, i is assigned to x.


The C Null Statement

A “null statement” is a statement containing only a semicolon; it can appear wherever a statement is expected. Nothing happens when a null statement is executed. The correct way to code a null statement is:

Syntax

;

Statements such as do, for, if, and while require that an executable statement appear as the statement body. The null statement satisfies the syntax requirement in cases that do not need a substantive statement body.

As with any other C statement, you can include a label before a null statement. To label an item that is not a statement, such as the closing brace of a compound statement, you can label a null statement and insert it immediately before the item to get the same effect.

This example illustrates the null statement:

for ( i = 0; i < 10; line[i++] = 0 )
     ;

In this example, the loop expression of the for statement line[i++] = 0 initializes the first 10 elements of line to 0. The statement body is a null statement, since no further statements are necessary.


The C return Statement

The return statement terminates the execution of a function and returns control to the calling function. Execution resumes in the calling function at the point immediately following the call. A return statement can also return a value to the calling function. See Return Type for more information.

Syntax

jump-statement :

return expression opt ;

The value of expression, if present, is returned to the calling function. If expression is omitted, the return value of the function is undefined. The expression, if present, is converted to the type returned by the function. If the function was declared with return type void, a return statement containing an expression generates a warning and the expression is not evaluated.

If no return statement appears in a function definition, control automatically returns to the calling function after the last statement of the called function is executed. In this case, the return value of the called function is undefined. If a return value is not required, declare the function to have void return type; otherwise, the default return type is int.

Many programmers use parentheses to enclose the expression argument of the return statement. However, C does not require the parentheses.

This example demonstrates the return statement:

void draw( int I, long L );
long sq( int s );
int main()
{
    long y;
    int x;

    y = sq( x );
    draw( x, y );
    return();
}

long sq( int s )
{
    return( s * s );
}

void draw( int I, long L )
{
    /* Statements defining the draw function here */
    return;
}

In this example, the main function calls two functions: sq and draw. The sq function returns the value of x * x to main, where the return value is assigned to y. The draw function is declared as a void function and does not return a value. An attempt to assign the return value of draw would cause a diagnostic message to be issued.


The C switch Statement

The switch and case statements help control complex conditional and branching operations. The switch statement transfers control to a statement within its body.

Syntax

selection-statement :

switch ( expression ) statement

labeled-statement :

case constant-expression : statement
default : statement

Control passes to the statement whose case constant-expression matches the value of switch ( expression ). The switch statement can include any number of case instances, but no two case constants within the same switch statement can have the same value. Execution of the statement body begins at the selected statement and proceeds until the end of the body or until a break statement transfers control out of the body.

Use of the switch statement usually looks something like this:

switch ( expression )
{
declarations
.
.
.
case constant-expression :

statements executed if the expression equals the
value of this constant-expression
.
.
.
break;
default :
statements executed if expression does not equal
any case constant-expression
}

You can use the break statement to end processing of a particular case within the switch statement and to branch to the end of the switch statement. Without break, the program continues to the next case, executing the statements until a break or the end of the statement is reached. In some situations, this continuation may be desirable.

The default statement is executed if no case constant-expression is equal to the value of switch ( expression ). If the default statement is omitted, and no case match is found, none of the statements in the switch body are executed. There can be at most one default statement. The default statement need not come at the end; it can appear anywhere in the body of the switch statement. In fact it is often more efficient if it appears at the beginning of the switch statement. A case or default label can only appear inside a switch statement.

The type of switch expression and case constant-expression must be integral. The value of each case constant-expression must be unique within the statement body.

The case and default labels of the switch statement body are significant only in the initial test that determines where execution starts in the statement body. Switch statements can be nested. Any static variables are initialized before executing into any switch statements.

Note Declarations can appear at the head of the compound statement forming the switch body, but initializations included in the declarations are not performed. The switch statement transfers control directly to an executable statement within the body, bypassing the lines that contain initializations.

The following examples illustrate switch statements:

switch( c )
{
    case 'A':
        capa++;
    case 'a':
        lettera++;
    default :
        total++;
}

All three statements of the switch body in this example are executed if c is equal to 'A' since a break statement does not appear before the following case. Execution control is transferred to the first statement (capa++;) and continues in order through the rest of the body. If c is equal to 'a', lettera and total are incremented. Only total is incremented if c is not equal to 'A' or 'a'.

switch( i )
{
    case -1:
        n++;
        break;
    case 0 :
        z++;
        break;
    case 1 :
        p++;
        break;
}

In this example, a break statement follows each statement of the switch body. The break statement forces an exit from the statement body after one statement is executed. If i is equal to –1, only n is incremented. The break following the statement n++; causes execution control to pass out of the statement body, bypassing the remaining statements. Similarly, if i is equal to 0, only z is incremented; if i is equal to 1, only p is incremented. The final break statement is not strictly necessary, since control passes out of the body at the end of the compound statement, but it is included for consistency.

A single statement can carry multiple case labels, as the following example shows:

case 'a' :
case 'b' :
case 'c' :
case 'd' :
case 'e' :
case 'f' :  hexcvt(c);

In this example, if constant-expression equals any letter between 'a' and 'f', the hexcvt function is called.

Microsoft Specific —>

Microsoft C does not limit the number of case values in a switch statement. The number is limited only by the available memory. ANSI C requires at least 257 case labels be allowed in a switch statement.

The default for Microsoft C is that the Microsoft extensions are enabled. Use the /Za compiler option to disable these extensions.

END Microsoft Specific


The try-except Statement

Microsoft Specific —>

The try-except statement is a Microsoft extension to the C language that enables applications to gain control of a program when events that normally terminate execution occur. Such events are called exceptions, and the mechanism that deals with exceptions is called structured exception handling.

Exceptions can be either hardware- or software-based. Even when applications cannot completely recover from hardware or software exceptions, structured exception handling makes it possible to display error information and trap the internal state of the application to help diagnose the problem. This is especially useful for intermittent problems that cannot be reproduced easily.

Syntax

try-except-statement :

__try compound-statement
__except ( expression ) compound-statement

The compound statement after the __try clause is the guarded section. The compound statement after the __except clause is the exception handler. The handler specifies a set of actions to be taken if an exception is raised during execution of the guarded section. Execution proceeds as follows:

  1. The guarded section is executed.

  2. If no exception occurs during execution of the guarded section, execution continues at the statement after the __except clause.

  3. If an exception occurs during execution of the guarded section or in any routine the guarded section calls, the__except expression is evaluated and the value returned determines how the exception is handled. There are three values:

    EXCEPTION_CONTINUE_SEARCH Exception is not recognized. Continue to search up the stack for a handler, first for containing try-except statements, then for handlers with the next highest precedence.

    EXCEPTION_CONTINUE_EXECUTION Exception is recognized but dismissed. Continue execution at the point where the exception occurred.

    EXCEPTION_EXECUTE_HANDLER Exception is recognized. Transfer control to the exception handler by executing the __except compound statement, then continue execution at the point the exception occurred.

Because the __except expression is evaluated as a C expression, it is limited to a single value, the conditional-expression operator, or the comma operator. If more extensive processing is required, the expression can call a routine that returns one of the three values listed above.

Note Structured exception handling works with C and C++ source files. However, it is not specifically designed for C++. You can ensure that your code is more portable by using C++ exception handling. Also, the C++ exception handling mechanism is much more flexible, in that it can handle exceptions of any type.

For C++ programs, C++ exception handling should be used instead of structured exception handling. For more information, see Exception Handling in the C++ Language Reference.

Each routine in an application can have its own exception handler. The __except expression executes in the scope of the __try body. This means it has access to any local variables declared there.

The __leave keyword is valid within a try-except statement block. The effect of __leave is to jump to the end of the try-except block. Execution resumes after the end of the exception handler. Although a goto statement can be used to accomplish the same result, a goto statement causes stack unwinding. The __leave statement is more efficient because it does not involve stack unwinding.

Exiting a try-except statement using the longjmp run-time function is considered abnormal termination. It is illegal to jump into a __try statement, but legal to jump out of one. The exception handler is not called if a process is killed in the middle of executing a try-except statement.

Example

Following is an example of an exception handler and a termination handler. See The try-finally Statement for more information about termination handlers.

.
.
.
puts("hello");
__try{
   puts("in try");
   __try{
      puts("in try");
      RAISE_AN_EXCEPTION();
   }__finally{
      puts("in finally");
   }
}__except( puts("in filter"), EXCEPTION_EXECUTE_HANDLER ){
   puts("in except");
}
puts("world");

This is the output from the example, with commentary added on the right:

hello
in try              /* fall into try                     */
in try              /* fall into nested try                */
in filter           /* execute filter; returns 1 so accept  */
in finally          /* unwind nested finally                */
in except           /* transfer control to selected handler */
world               /* flow out of handler                  */

END Microsoft Specific


The try-finally Statement

Microsoft Specific —>

The try-finally statement is a Microsoft extension to the C language that enables applications to guarantee execution of cleanup code when execution of a block of code is interrupted. Cleanup consists of such tasks as deallocating memory, closing files, and releasing file handles. The try-finally statement is especially useful for routines that have several places where a check is made for an error that could cause premature return from the routine.

Syntax

try-finally-statement :

__try compound-statement
__finally compound-statement

The compound statement after the __try clause is the guarded section. The compound statement after the __finally clause is the termination handler. The handler specifies a set of actions that execute when the guarded section is exited, whether the guarded section is exited by an exception (abnormal termination) or by standard fall through (normal termination).

Control reaches a __try statement by simple sequential execution (fall through). When control enters the __try statement, its associated handler becomes active. Execution proceeds as follows:

  1. The guarded section is executed.

  2. The termination handler is invoked.

  3. When the termination handler completes, execution continues after the __finally statement. Regardless of how the guarded section ends (for example, via a goto statement out of the guarded body or via a return statement), the termination handler is executed before the flow of control moves out of the guarded section.

The __leave keyword is valid within a try-finally statement block. The effect of __leave is to jump to the end of the try-finally block. The termination handler is immediately executed. Although a goto statement can be used to accomplish the same result, a goto statement causes stack unwinding. The __leave statement is more efficient because it does not involve stack unwinding.

Exiting a try-finally statement using a return statement or the longjmp run-time function is considered abnormal termination. It is illegal to jump into a __try statement, but legal to jump out of one. All __finally statements that are active between the point of departure and the destination must be run. This is called a “local unwind.”

The termination handler is not called if a process is killed while executing a try-finally statement.

Note Structured exception handling works with C and C++ source files. However, it is not specifically designed for C++. You can ensure that your code is more portable by using C++ exception handling. Also, the C++ exception handling mechanism is much more flexible, in that it can handle exceptions of any type.

For C++ programs, C++ exception handling should be used instead of structured exception handling. For more information, see Exception Handling in the C++ Language Reference.

See the example for the try-except statement to see how the try-finally statement works.

END Microsoft Specific


The C while Statement

The while statement lets you repeat a statement until a specified expression becomes false.

Syntax

iteration-statement :

while ( expression ) statement

The expression must have arithmetic or pointer type. Execution proceeds as follows:

  1. The expression is evaluated.

  2. If expression is initially false, the body of the while statement is never executed, and control passes from the while statement to the next statement in the program.

    If expression is true (nonzero), the body of the statement is executed and the process is repeated beginning at step 1.

The while statement can also terminate when a break, goto, or return within the statement body is executed. Use the continue statement to terminate an iteration without exiting the while loop. The continue statement passes control to the next iteration of the while statement.

This is an example of the while statement:

while ( i >= 0 )
{
    string1[i] = string2[i];
    i--;
}

This example copies characters from string2 to string1. If i is greater than or equal to 0, string2[i] is assigned to string1[i] and i is decremented. When i reaches or falls below 0, execution of the while statement terminates.


Functions

The function is the fundamental modular unit in C. A function is usually designed to perform a specific task, and its name often reflects that task. A function contains declarations and statements. This chapter describes how to declare, define, and call C functions. Other topics discussed are:

  • Overview of functions

  • Function attributes

  • Specifying calling conventions

  • Inline functions

  • DLL export and import functions

  • Naked functions

  • Storage class

  • Return type

  • Arguments

  • Parameters


Overview of Functions

Functions must have a definition and should have a declaration, although a definition can serve as a declaration if the declaration appears before the function is called. The function definition includes the function body — the code that executes when the function is called.

A function declaration establishes the name, return type, and attributes of a function that is defined elsewhere in the program. A function declaration must precede the call to the function. This is why the header files containing the declarations for the run-time functions are included in your code before a call to a run-time function. If the declaration has information about the types and number of parameters, the declaration is a prototype. See Function Prototypes for more information.

The compiler uses the prototype to compare the types of arguments in subsequent calls to the function with the function’s parameters and to convert the types of the arguments to the types of the parameters whenever necessary.

A function call passes execution control from the calling function to the called function. The arguments, if any, are passed by value to the called function. Execution of a return statement in the called function returns control and possibly a value to the calling function.


Obsolete Forms of Function Declarations and Definitions

The old-style function declarations and definitions use slightly different rules for declaring parameters than the syntax recommended by the ANSI C standard. First, the old-style declarations don’t have a parameter list. Second, in the function definition, the parameters are listed, but their types are not declared in the parameter list. The type declarations precede the compound statement constituting the function body. The old-style syntax is obsolete and should not be used in new code. Code using the old-style syntax is still supported, however. This example illustrates the obsolete forms of declarations and definitions:

double old_style();           /* Obsolete function declaration */

double alt_style( a , real )  /* Obsolete function definition */
    double *real;
    int a;
{
    return ( *real + a ) ;
}

Functions returning an integer or pointer with the same size as an int are not required to have a declaration although the declaration is recommended.

To comply with the ANSI C standard, old-style function declarations using an ellipsis now generate an error when compiling with the /Za option and a level 4 warning when compiling with /Ze. For example:

void funct1( a, ... )  /* Generates a warning under /Ze or */
int a;                 /* an error when compiling with /Za */
{
}

You should rewrite this declaration as a prototype:

void funct1( int a, ... )
{
}

Old-style function declarations also generate warnings if you subsequently declare or define the same function with either an ellipsis or a parameter with a type that is not the same as its promoted type.

The next section, C Function Definitions, shows the syntax for function definitions, including the old-style syntax. The nonterminal for the list of parameters in the old-style syntax is identifier-list.


C Function Definitions

A function definition specifies the name of the function, the types and number of parameters it expects to receive, and its return type. A function definition also includes a function body with the declarations of its local variables, and the statements that determine what the function does.

Syntax

translation-unit :

external-declaration
translation-unit external-declaration

external-declaration : /* Allowed only at external (file) scope */

function-definition
declaration

function-definition : /* Declarator here is the function declarator */

declaration-specifiersopt attribute-seqopt declarator declaration-listopt compound-statement
/* attribute-seq is Microsoft Specific */

Prototype parameters are:

declaration-specifiers :

storage-class-specifier declaration-specifiers opt
type-specifier declaration-specifiers opt
type-qualifier declaration-specifiers opt

declaration-list :

declaration
declaration-list declaration

declarator :

pointeropt direct-declarator

direct-declarator : /* A function declarator */

direct-declarator ( parameter-type-list ) /* New-style declarator */
direct-declarator ( identifier-list opt ) /* Obsolete-style declarator */

The parameter list in a definition uses this syntax:

parameter-type-list : /* The parameter list */

parameter-list
parameter-list , ...

parameter-list :

parameter-declaration
parameter-list , parameter-declaration

parameter-declaration :

declaration-specifiers declarator
declaration-specifiers abstract-declarator opt

The parameter list in an old-style function definition uses this syntax:

identifier-list : /* Used in obsolete-style function definitions and declarations */

identifier
identifier-list , identifier

The syntax for the function body is:

compound-statement : /* The function body */

{ declaration-list opt statement-list opt }

The only storage-class specifiers that can modify a function declaration are extern and static. The extern specifier signifies that the function can be referenced from other files; that is, the function name is exported to the linker. The static specifier signifies that the function cannot be referenced from other files; that is, the name is not exported by the linker. If no storage class appears in a function definition, extern is assumed. In any case, the function is always visible from the definition point to the end of the file.

The optional declaration-specifiers and mandatory declarator together specify the function’s return type and name. The declarator is a combination of the identifier that names the function and the parentheses following the function name. The optional attribute-seq nonterminal is a Microsoft-specific feature defined in Function Attributes.

The direct-declarator (in the declarator syntax) specifies the name of the function being defined and the identifiers of its parameters. If the direct-declarator includes a parameter-type-list, the list specifies the types of all the parameters. Such a declarator also serves as a function prototype for later calls to the function.

A declaration in the declaration-list in function definitions cannot contain a storage-class-specifier other than register. The type-specifier in the declaration-specifiers syntax can be omitted only if the register storage class is specified for a value of int type.

The compound-statement is the function body containing local variable declarations, references to externally declared items, and statements.

The sections Function Attributes, Storage Class, Return Type, Parameters, and Function Body describe the components of the function definition in detail.


Function Attributes

Microsoft Specific —>

The optional attribute-seq nonterminal allows you to select a calling convention on a per-function basis. You can also specify functions as __fastcall or __inline.

END Microsoft Specific


Specifying Calling Conventions

Microsoft Specific —>

For information on calling conventions, see Calling Conventions Topics in Visual C++ Programmer’s Guide.

END Microsoft Specific


Inline Functions

Microsoft Specific —>

The __inline keyword tells the compiler to substitute the code within the function definition for every instance of a function call. However, substitution occurs only at the compiler’s discretion. For example, the compiler does not inline a function if its address is taken or if it is too large to inline.

For a function to be considered as a candidate for inlining, it must use the new-style function definition.

Use this form to specify an inline function:

__inline type opt function-definition;

The use of inline functions generates faster code and can sometimes generate smaller code than the equivalent function call generates for the following reasons:

  • It saves the time required to execute function calls.

  • Small inline functions, perhaps three lines or less, create less code than the equivalent function call because the compiler doesn’t generate code to handle arguments and a return value.

  • Functions generated inline are subject to code optimizations not available to normal functions because the compiler does not perform interprocedural optimizations.

Functions using __inline should not be confused with inline assembler code. See Inline Assembler for more information.

END Microsoft Specific


The C Inline Assembler

Microsoft Specific —>

The inline assembler lets you embed assembly-language instructions directly in your C source programs without extra assembly and link steps. The inline assembler is built into the compiler — you don’t need a separate assembler such as the Microsoft Macro Assembler (MASM).

Because the inline assembler doesn’t require separate assembly and link steps, it is more convenient than a separate assembler. Inline assembly code can use any C variable or function name that is in scope, so it is easy to integrate it with your program’s C code. And because the assembly code can be mixed with C statements, it can do tasks that are cumbersome or impossible in C alone.

The __asm keyword invokes the inline assembler and can appear wherever a C statement is legal. It cannot appear by itself. It must be followed by an assembly instruction, a group of instructions enclosed in braces, or, at the very least, an empty pair of braces. The term “__asm block” here refers to any instruction or group of instructions, whether or not in braces.

The code below is a simple __asm block enclosed in braces. (The code is a custom function prolog sequence.)

__asm
{
   push ebp
   mov  ebp, esp
   sub  esp, __LOCAL_SIZE
}

Alternatively, you can put __asm in front of each assembly instruction:

__asm push ebp
__asm mov  ebp, esp
__asm sub  esp, __LOCAL_SIZE

Since the __asm keyword is a statement separator, you can also put assembly instructions on the same line:

__asm push ebp   __asm mov  ebp, esp   __asm sub  esp, __LOCAL_SIZE

END Microsoft Specific


DLL Import and Export Functions

Microsoft Specific —>

The dllimport and dllexport storage-class modifiers are Microsoft-specific extensions to the C language. These modifiers explicitly define the DLL’s interface to its client (the executable file or another DLL). Declaring functions as dllexport eliminates the need for a module-definition (.DEF) file. You can also use the dllimport and dllexport modifiers with data and objects.

The dllimport and dllexport storage-class modifiers must be used with the extended attribute syntax keyword, __declspec, as shown in this example:

#define DllImport   __declspec( dllimport )
#define DllExport   __declspec( dllexport )

DllExport void func();
DllExport int i = 10;
DllExport int j;
DllExport int n;

For specific information about the syntax for extended storage-class modifiers, see Extended Storage-Class Attributes in Chapter 3.

END Microsoft Specific


Definitions and Declarations

Microsoft Specific —>

The DLL interface refers to all items (functions and data) that are known to be exported by some program in the system; that is, all items that are declared as dllimport or dllexport. All declarations included in the DLL interface must specify either the dllimport or dllexport attribute. However, the definition can specify only the dllexport attribute. For example, the following function definition generates a compiler error:

#define DllImport   __declspec( dllimport )
#define DllExport   __declspec( dllexport )

DllImport int func()    /* Error; dllimport prohibited in */
                        /* definition. */
{
   return 1;
}

This code also generates an error:

#define DllImport   __declspec( dllimport )
#define DllExport   __declspec( dllexport )

DllImport int i = 10;      /* Error; this is a definition. */

However, this is correct syntax:

#define DllImport   __declspec( dllimport )
#define DllExport   __declspec( dllexport )

DllExport int i = 10;      /* Okay: this is an export definition. */

The use of dllexport implies a definition, while dllimport implies a declaration. You must use the extern keyword with dllexport to force a declaration; otherwise, a definition is implied.

#define DllImport   __declspec( dllimport )
#define DllExport   __declspec( dllexport )

extern DllImport int k;   /* These are correct and imply */
Dllimport int j;          /* a declaration. */

END Microsoft Specific


Defining Inline C Functions with dllexport and dllimport

Microsoft Specific —>

You can define as inline a function with the dllexport attribute. In this case, the function is always instantiated and exported, whether or not any module in the program references the function. The function is presumed to be imported by another program.

You can also define as inline a function declared with the dllimport attribute. In this case, the function can be expanded (subject to the /Ob (inline) compiler option specification) but never instantiated. In particular, if the address of an inline imported function is taken, the address of the function residing in the DLL is returned. This behavior is the same as taking the address of a non-inline imported function.

Static local data and strings in inline functions maintain the same identities between the DLL and client as they would in a single program (that is, an executable file without a DLL interface).

Exercise care when providing imported inline functions. For example, if you update the DLL, don’t assume that the client will use the changed version of the DLL. To ensure that you are loading the proper version of the DLL, rebuild the DLL’s client as well.

END Microsoft Specific


Rules and Limitations for dllimport/dllexport

Microsoft Specific —>

  • If you declare a function without the dllimport or dllexport attribute, the function is not considered part of the DLL interface. Therefore, the definition of the function must be present in that module or in another module of the same program. To make the function part of the DLL interface, you must declare the definition of the function in the other module as dllexport. Otherwise, a linker error is generated when the client is built.

  • If a single module in your program contains dllimport and dllexport declarations for the same function, the dllexport attribute takes precedence over the dllimport attribute. However, a compiler warning is generated. For example:
    #define DllImport    __declspec( dllimport )
#define DllExport    __declspec( dllexport )

DllImport void func1( void );
DllExport void func1( void );   /* Warning; dllexport */
                                /* takes precedence. */
  • You cannot initialize a static data pointer with the address of a data object declared with the dllimport attribute. For example, the following code generates errors:
    #define DllImport    __declspec( dllimport )
#define DllExport    __declspec( dllexport )

DllImport int i;
.
.
.
int *pi = &i;                           /* Error */

void func2()
{
static int *pi = &i;                   /* Error */
}
  • Initializing a static function pointer with the address of a function declared with dllimport sets the pointer to the address of the DLL import thunk (a code stub that transfers control to the function) rather than the address of the function. This assignment does not generate an error message:
    #define DllImport    __declspec( dllimport )
#define DllExport    __declspec( dllexport )

DllImport void func1( void
.
.
.
static void ( *pf )( void ) = &func1;   /* No Error */

void func2()
{
static void ( *pf )( void ) = &func1;  /* No Error */
}
  • Because a program that includes the dllexport attribute in the declaration of an object must provide the definition for that object, you can initialize a global or local static function pointer with the address of a dllexport function. Similarly, you can initialize a global or local static data pointer with the address of a dllexport data object. For example:
    #define DllImport    __declspec( dllimport )
#define DllExport    __declspec( dllexport )

DllImport void func1( void );
DllImport int i;

DllExport void func1( void );
DllExport int i;
.
.
.
int *pi = &i;                            /* Okay */
static void ( *pf )( void ) = &func1;    /* Okay */

void func2()
{
static int *pi = i;                     /* Okay */
static void ( *pf )( void ) = &func1;   /* Okay */
}

END Microsoft Specific


Naked Functions

Microsoft Specific —>

The naked storage-class attribute is a Microsoft-specific extension to the C language. For functions declared with the naked storage-class attribute, the compiler generates code without prolog and epilog code. You can use this feature to write your own prolog/epilog code sequences using inline assembler code. Naked functions are particularly useful in writing virtual device drivers.

Because the naked attribute is only relevant to the definition of a function and is not a type modifier, naked functions use the extended attribute syntax, described in Extended Storage-Class Attributes in Chapter 3.

The following example defines a function with the naked attribute:

__declspec( naked ) int func( formal_parameters )
{
   /* Function body */
}

Or, alternatively:

#define Naked   __declspec( naked )

Naked int func( formal_parameters )
{
   /* Function body */
}

The naked attribute affects only the nature of the compiler’s code generation for the function’s prolog and epilog sequences. It does not affect the code that is generated for calling such functions. Thus, the naked attribute is not considered part of the function’s type, and function pointers cannot have the naked attribute. Furthermore, the naked attribute cannot be applied to a data definition. For example, the following code generates errors:

__declspec( naked ) int i;  /* Error--naked attribute not */
                            /* permitted on data declarations. */

The naked attribute is relevant only to the definition of the function and cannot be specified in the function’s prototype. The following declaration generates a compiler error:

__declspec( naked ) int func();   /* Error--naked attribute not */
                     /* permitted on function declarations.    */   \

END Microsoft Specific


Rules and Limitations for Using Naked Functions

Microsoft Specific —>

  • The return statement is not permitted in a naked function. However, you can return an int by moving the return value into the EAX register before the RET instruction.

  • Structured exception handling constructs are not permitted in a naked function, because the constructs must unwind across the stack frame.

  • The setjmp run-time function is not permitted in a naked function, because it too must unwind across the stack frame. However, the longjmp run-time function is permitted.

  • The _alloca function is not permitted in a naked function.

  • To ensure that no initialization code for local variables appears before the prolog sequence, initialized local variables are not permitted at function scope.

  • Frame pointer optimization (the /Oy compiler option) is not recommended, but it is automatically suppressed for a naked function.

END Microsoft Specific


Considerations when Writing Prolog/Epilog Code

Microsoft Specific —>

Before writing your own prolog and epilog code sequences, it is important to understand how the stack frame is laid out. It is also useful to know how to use the __LOCAL_SIZE predefined constant.

C Stack Frame Layout

This example shows the standard prolog code that might appear in a 32-bit function:

push     ebp                 ; Save ebp
mov      ebp, esp            ; Set stack frame pointer
sub      esp, localbytes     ; Allocate space for locals
push     <registers>         ; Save registers

The localbytes variable represents the number of bytes needed on the stack for local variables, and the registers variable is a placeholder that represents the list of registers to be saved on the stack. After pushing the registers, you can place any other appropriate data on the stack. The following is the corresponding epilog code:

pop      <registers>         ; Restore registers
mov      esp, ebp            ; Restore stack pointer
pop      ebp                 ; Restore ebp
ret                          ; Return from function

The stack always grows down (from high to low memory addresses). The base pointer (ebp) points to the pushed value of ebp. The local variables area begins at ebp-2. To access local variables, calculate an offset from ebp by subtracting the appropriate value from ebp.

The __LOCAL_SIZE Constant

The compiler provides a constant, __LOCAL_SIZE, for use in the inline assembler block of function prolog code. This constant is used to allocate space for local variables on the stack frame in custom prolog code.

The compiler determines the value of __LOCAL_SIZE. The value is the total number of bytes of all user-defined local variables and compiler-generated temporary variables. __LOCAL_SIZE can be used only as an immediate operand; it cannot be used in an expression. You must not change or redefine the value of this constant. For example:

mov      eax, __LOCAL_SIZE           ;Immediate operand--Okay
mov      eax, [ebp - __LOCAL_SIZE]   ;Error

The following example of a naked function containing custom prolog and epilog sequences uses __LOCAL_SIZE in the prolog sequence:

__declspec ( naked ) func()
{
   int i;
   int j;

   __asm      /* prolog */
      {
      push   ebp
      mov      ebp, esp
      sub      esp, __LOCAL_SIZE
      }

   /* Function body */

   __asm      /* epilog */
      {
      mov      esp, ebp
      pop      ebp
      ret
      }
}

END Microsoft Specific


Storage Class

The storage-class specifier in a function definition gives the function either extern or static storage class.

Syntax

function-definition :

declaration-specifiers opt attribute-seq opt declarator declaration-list opt compound-statement
/* attribute-seq is Microsoft Specific */

declaration-specifiers :

storage-class-specifier declaration-specifiers opt
type-specifier declaration-specifiers opt
type-qualifier declaration-specifiers opt

storage-class-specifier : /* For function definitions */

extern
static

If a function definition does not include a storage-class-specifier, the storage class defaults to extern. You can explicitly declare a function as extern, but it is not required.

If the declaration of a function contains the storage-class-specifier extern, the identifier has the same linkage as any visible declaration of the identifier with file scope. If there is no visible declaration with file scope, the identifier has external linkage. If an identifier has file scope and no storage-class-specifier, the identifier has external linkage. External linkage means that each instance of the identifier denotes the same object or function. See Lifetime, Scope, Visibility, and Linkage in Chapter 2 for more information about linkage and file scope.

Block-scope function declarations with a storage-class specifier other than extern generate errors.

A function with static storage class is visible only in the source file in which it is defined. All other functions, whether they are given extern storage class explicitly or implicitly, are visible throughout all source files in the program. If static storage class is desired, it must be declared on the first occurrence of a declaration (if any) of the function, and on the definition of the function.

Microsoft Specific —>

When the Microsoft extensions are enabled, a function originally declared without a storage class (or with extern storage class) is given static storage class if the function definition is in the same source file and if the definition explicitly specifies static storage class.

When compiling with the /Ze compiler option, functions declared within a block using the extern keyword have global visibility. This is not true when compiling with /Za. This feature should not be relied upon if portability of source code is a consideration.

END Microsoft Specific


Return Type

The return type of a function establishes the size and type of the value returned by the function and corresponds to the type-specifier in the syntax below:

Syntax

function-definition :

declaration-specifiers opt attribute-seq opt declarator declaration-list opt compound-statement
/* attribute-seq is Microsoft Specific */

declaration-specifiers :

storage-class-specifier declaration-specifiers opt
type-specifier declaration-specifiers opt
type-qualifier declaration-specifiers opt

type-specifier :

void
char
short
int
long
float
double
signed
unsigned
struct-or-union-specifier
enum-specifier
typedef-name

The type-specifier can specify any fundamental, structure, or union type. If you do not include type-specifier, the return type int is assumed.

The return type given in the function definition must match the return type in declarations of the function elsewhere in the program. A function returns a value when a return statement containing an expression is executed. The expression is evaluated, converted to the return value type if necessary, and returned to the point at which the function was called. If a function is declared with return type void, a return statement containing an expression generates a warning and the expression is not evaluated.

The following examples illustrate function return values.

typedef struct
{
    char name[20];
    int id;
    long class;
} STUDENT;

/* Return type is STUDENT: */

STUDENT sortstu( STUDENT a, STUDENT b )
{
    return ( (a.id < b.id) ? a : b );
}

This example defines the STUDENT type with a typedef declaration and defines the function sortstu to have STUDENT return type. The function selects and returns one of its two structure arguments. In subsequent calls to the function, the compiler checks to make sure the argument types are STUDENT.

Note Efficiency would be enhanced by passing pointers to the structure, rather than the entire structure.

char *smallstr( char s1[], char s2[] )
{
    int i;

    i = 0;
    while ( s1[i] != '\0' && s2[i] != '\0' )
        i++;
    if ( s1[i] == '\0' )
        return ( s1 );
    else
        return ( s2 );
}

This example defines a function returning a pointer to an array of characters. The function takes two character arrays (strings) as arguments and returns a pointer to the shorter of the two strings. A pointer to an array points to the first of the array elements and has its type; thus, the return type of the function is a pointer to type char.

You need not declare functions with int return type before you call them, although prototypes are recommended so that correct type checking for arguments and return values is enabled.


Parameters

Arguments are names of values passed to a function by a function call. Parameters are the values the function expects to receive. In a function prototype, the parentheses following the function name contain a complete list of the function’s parameters and their types. Parameter declarations specify the types, sizes, and identifiers of values stored in the parameters.

Syntax

function-definition :

declaration-specifiers opt attribute-seq opt declarator declaration-list opt compound-statement
/* attribute-seq is Microsoft Specific */

declarator :

pointer opt direct-declarator

direct-declarator :/* A function declarator */

direct-declarator ( parameter-type-list ) /* New-style declarator */

parameter-type-list : /* A parameter list */

parameter-list
parameter-list , ...

parameter-list :

parameter-declaration
parameter-list , parameter-declaration

parameter-declaration :

declaration-specifiers declarator
declaration-specifiers abstract-declarator opt

The parameter-type-list is a sequence of parameter declarations separated by commas. The form of each parameter in a parameter list looks like this:

[register] type-specifier [declarator]

Function parameters declared with the auto attribute generate errors. The identifiers of the parameters are used in the function body to refer to the values passed to the function. You can name the parameters in a prototype, but the names go out of scope at the end of the declaration. Therefore parameter names can be assigned the same way or differently in the function definition. These identifiers cannot be redefined in the outermost block of the function body, but they can be redefined in inner, nested blocks as though the parameter list were an enclosing block.

Each identifier in parameter-type-list must be preceded by its appropriate type specifier, as shown in this example:

void new( double x, double y, double z )
{
    /* Function body here */
}

If at least one parameter occurs in the parameter list, the list can end with a comma followed by three periods (, ...). This construction, called the “ellipsis notation,” indicates a variable number of arguments to the function. (See Calls with a Variable Number of Arguments for more information.) However, a call to the function must have at least as many arguments as there are parameters before the last comma.

If no arguments are to be passed to the function, the list of parameters is replaced by the keyword void. This use of void is distinct from its use as a type specifier.

The order and type of parameters, including any use of the ellipsis notation, must be the same in all the function declarations (if any) and in the function definition. The types of the arguments after usual arithmetic conversions must be assignment-compatible with the types of the corresponding parameters. (See Usual Arithmetic Conversions in Chapter 4 for information on arithmetic conversions.) Arguments following the ellipsis are not checked. A parameter can have any fundamental, structure, union, pointer, or array type.

The compiler performs the usual arithmetic conversions independently on each parameter and on each argument, if necessary. After conversion, no parameter is shorter than an int, and no parameter has float type unless the parameter type is explicitly specified as float in the prototype. This means, for example, that declaring a parameter as a char has the same effect as declaring it as an int.


Function Body

A “function body” is a compound statement containing the statements that specify what the function does.

Syntax

function-definition :

declaration-specifiers opt attribute-seq opt declarator declaration-list opt compound-statement
/* attribute-seq is Microsoft Specific */

compound-statement : /* The function body */

{ declaration-list opt statement-list opt }

Variables declared in a function body, “local variables,” have auto storage class unless otherwise specified. When the function is called, storage is created for the local variables and local initializations are performed. Execution control passes to the first statement in compound-statement and continues until a return statement is executed or the end of the function body is encountered. Control then returns to the point at which the function was called.

A return statement containing an expression must be executed if the function is to return a value. The return value of a function is undefined if no return statement is executed or if the return statement does not include an expression.


Function Prototypes

A function declaration precedes the function definition and specifies the name, return type, storage class, and other attributes of a function. To be a prototype, the function declaration must also establish types and identifiers for the function’s arguments.

Syntax

declaration :

declaration-specifiers attribute-seq opt init-declarator-list opt ;
/* attribute-seqopt is Microsoft Specific */

declaration-specifiers :

storage-class-specifier declaration-specifiers opt
type-specifier declaration-specifiers opt
type-qualifier declaration-specifiers opt

init-declarator-list :

init-declarator
init-declarator-list , init-declarator

init-declarator :

declarator
declarator = initializer

declarator :

pointer opt direct-declarator

direct-declarator : /* A function declarator */

direct-declarator ( parameter-type-list ) /* New-style declarator */
direct-declarator ( identifier-list opt ) /* Obsolete-style declarator */

The prototype has the same form as the function definition, except that it is terminated by a semicolon immediately following the closing parenthesis and therefore has no body. In either case, the return type must agree with the return type specified in the function definition.

Function prototypes have the following important uses:

  • They establish the return type for functions that return types other than int. Although functions that return int values do not require prototypes, prototypes are recommended.

  • Without complete prototypes, standard conversions are made, but no attempt is made to check the type or number of arguments with the number of parameters.

  • Prototypes are used to initialize pointers to functions before those functions are defined.

  • The parameter list is used for checking the correspondence of arguments in the function call with the parameters in the function definition.

The converted type of each parameter determines the interpretation of the arguments that the function call places on the stack. A type mismatch between an argument and a parameter may cause the arguments on the stack to be misinterpreted. For example, on a 16-bit computer, if a 16-bit pointer is passed as an argument, then declared as a long parameter, the first 32 bits on the stack are interpreted as a long parameter. This error creates problems not only with the long parameter, but with any parameters that follow it. You can detect errors of this kind by declaring complete function prototypes for all functions.

A prototype establishes the attributes of a function so that calls to the function that precede its definition (or occur in other source files) can be checked for argument-type and return-type mismatches. For example, if you specify the static storage-class specifier in a prototype, you must also specify the static storage class in the function definition.

Complete parameter declarations (int a) can be mixed with abstract declarators (int) in the same declaration. For example, the following declaration is legal:

int add( int a, int );

The prototype can include both the type of, and an identifier for, each expression that is passed as an argument. However, such identifiers have scope only until the end of the declaration. The prototype can also reflect the fact that the number of arguments is variable, or that no arguments are passed. Without such a list, mismatches may not be revealed, so the compiler cannot generate diagnostic messages concerning them. See Arguments for more information on type checking.

Prototype scope in the Microsoft C compiler is now ANSI-compliant when compiling with the /Za compiler option. This means that if you declare a struct or union tag within a prototype, the tag is entered at that scope rather than at global scope. For example, when compiling with /Za for ANSI compliance, you can never call this function without getting a type mismatch error:

void func1( struct S * );

To correct your code, define or declare the struct or union at global scope before the function prototype:

struct S;
void func1( struct S * );

Under /Ze, the tag is still entered at global scope.


Function Calls

A function call is an expression that passes control and arguments (if any) to a function and has the form

expression ( expression-list opt )

where expression is a function name or evaluates to a function address and expression-list is a list of expressions (separated by commas). The values of these latter expressions are the arguments passed to the function. If the function does not return a value, then you declare it to be a function that returns void.

If a declaration exists before the function call, but no information is given concerning the parameters, any undeclared arguments simply undergo the usual arithmetic conversions.

Note The expressions in the function argument list can be evaluated in any order, so arguments whose values may be changed by side effects from another argument have undefined values. The sequence point defined by the function-call operator guarantees only that all side effects in the argument list are evaluated before control passes to the called function. (Note that the order in which arguments are pushed on the stack is a separate matter.) See Sequence Points in Chapter 4 for more information.

The only requirement in any function call is that the expression before the parentheses must evaluate to a function address. This means that a function can be called through any function-pointer expression.

Example

This example illustrates function calls called from a switch statement:

void main()
{
    /* Function prototypes */

    long lift( int ), step( int ), drop( int );
    void work( int number, long (*function)(int i) );

    int select, count;
    .
    .
    .
    select = 1;
    switch( select )
    {
        case 1: work( count, lift );
                break;

        case 2: work( count, step );
                break;

        case 3: work( count, drop );
                /* Fall through to next case */
        default:
                break;
    }
}

/* Function definition */

void work( int number, long (*function)(int i) )
{
    int i;
    long j;

    for ( i = j = 0; i < number; i++ )
            j += ( *function )( i );
}

In this example, the function call in main,

work( count, lift );

passes an integer variable, count, and the address of the function lift to the function work. Note that the function address is passed simply by giving the function identifier, since a function identifier evaluates to a pointer expression. To use a function identifier in this way, the function must be declared or defined before the identifier is used; otherwise, the identifier is not recognized. In this case, a prototype for work is given at the beginning of the main function.

The parameter function in work is declared to be a pointer to a function taking one int argument and returning a long value. The parentheses around the parameter name are required; without them, the declaration would specify a function returning a pointer to a long value.

The function work calls the selected function from inside the for loop by using the following function call:

( *function )( i );

One argument, i, is passed to the called function.


Arguments

The arguments in a function call have this form:

expression ( expression-list opt ) /* Function call */

In a function call, expression-list is a list of expressions (separated by commas). The values of these latter expressions are the arguments passed to the function. If the function takes no arguments, expression-list should contain the keyword void.

An argument can be any value with fundamental, structure, union, or pointer type. All arguments are passed by value. This means a copy of the argument is assigned to the corresponding parameter. The function does not know the actual memory location of the argument passed. The function uses this copy without affecting the variable from which it was originally derived.

Although you cannot pass arrays or functions as arguments, you can pass pointers to these items. Pointers provide a way for a function to access a value by reference. Since a pointer to a variable holds the address of the variable, the function can use this address to access the value of the variable. Pointer arguments allow a function to access arrays and functions, even though arrays and functions cannot be passed as arguments.

The order in which arguments are evaluated can vary under different compilers and different optimization levels. However, the arguments and any side effects are completely evaluated before the function is entered. See Side Effects in Chapter 4 for information on side effects.

The expression-list in a function call is evaluated and the usual arithmetic conversions are performed on each argument in the function call. If a prototype is available, the resulting argument type is compared to the prototype’s corresponding parameter. If they do not match, either a conversion is performed, or a diagnostic message is issued. The parameters also undergo the usual arithmetic conversions.

The number of expressions in expression-list must match the number of parameters, unless the function’s prototype or definition explicitly specifies a variable number of arguments. In this case, the compiler checks as many arguments as there are type names in the list of parameters and converts them, if necessary, as described above. See Calls with a Variable Number of Arguments for more information.

If the prototype’s parameter list contains only the keyword void, the compiler expects zero arguments in the function call and zero parameters in the definition. A diagnostic message is issued if it finds any arguments.

Example

This example uses pointers as arguments:

void main()
{
    /* Function prototype */

    void swap( int *num1, int *num2 );
    int x, y;
    .
    .
    .
    swap( &x, &y );  /* Function call */
}

/* Function definition */

void swap( int *num1, int *num2 )
{
    int t;

    t = *num1;
    *num1 = *num2;
    *num2 = t;
}

In this example, the swap function is declared in main to have two arguments, represented respectively by identifiers num1 and num2, both of which are pointers to int values. The parameters num1 and num2 in the prototype-style definition are also declared as pointers to int type values.

In the function call

swap( &x, &y )

the address of x is stored in num1 and the address of y is stored in num2. Now two names, or “aliases,” exist for the same location. References to *num1 and *num2 in swap are effectively references to x and y in main. The assignments within swap actually exchange the contents of x and y. Therefore, no return statement is necessary.

The compiler performs type checking on the arguments to swap because the prototype of swap includes argument types for each parameter. The identifiers within the parentheses of the prototype and definition can be the same or different. What is important is that the types of the arguments match those of the parameter lists in both the prototype and the definition.


Calls with a Variable Number of Arguments

A partial parameter list can be terminated by the ellipsis notation, a comma followed by three periods (, ...), to indicate that there may be more arguments passed to the function, but no more information is given about them. Type checking is not performed on such arguments. At least one parameter must precede the ellipsis notation and the ellipsis notation must be the last token in the parameter list. Without the ellipsis notation, the behavior of a function is undefined if it receives parameters in addition to those declared in the parameter list.

To call a function with a variable number of arguments, simply specify any number of arguments in the function call. An example is the printf function from the C run-time library. The function call must include one argument for each type name declared in the parameter list or the list of argument types.

All the arguments specified in the function call are placed on the stack unless the __fastcall calling convention is specified. The number of parameters declared for the function determines how many of the arguments are taken from the stack and assigned to the parameters. You are responsible for retrieving any additional arguments from the stack and for determining how many arguments are present. The STDARGS.H file contains ANSI-style macros for accessing arguments of functions which take a variable number of arguments. Also, the XENIX®- style macros in VARARGS.H are still supported.

This sample declaration is for a function that calls a variable number of arguments:

int average( int first, ...);

Microsoft Specific —>

To maintain compatibility with previous versions of Microsoft C, a Microsoft extension to the ANSI C standard allows a comma without trailing periods (,) at the end of the list of parameters to indicate a variable number of arguments. However, it is recommended that code be changed to incorporate the ellipsis notation.

END Microsoft Specific


Recursive Functions

Any function in a C program can be called recursively; that is, it can call itself. The number of recursive calls is limited to the size of the stack. See the Stack Allocations (/STACK) linker option in the Visual C++ Programmer’s Guide for information about linker options that set stack size. Each time the function is called, new storage is allocated for the parameters and for the auto and register variables so that their values in previous, unfinished calls are not overwritten. Parameters are only directly accessible to the instance of the function in which they are created. Previous parameters are not directly accessible to ensuing instances of the function.

Note that variables declared with static storage do not require new storage with each recursive call. Their storage exists for the lifetime of the program. Each reference to such a variable accesses the same storage area.

Example

This example illustrates recursive calls:

int factorial( int num );      /* Function prototype */

void main()
{
    int result, number;
    .
    .
    .
    result = factorial( number );
}

int factorial( int num )      /* Function definition */
{
    .
    .
    .
    if ( ( num > 0 ) || ( num <= 10 ) )
        return( num * factorial( num - 1 ) );
}


C Language Syntax Summary

This appendix gives the full description of the C language and the Microsoft-specific C language features. You can use the syntax notation in this appendix to determine the exact syntax for any language component. The explanation for the syntax appears in the section of this manual where a topic is discussed.

Note This syntax summary is not part of the ANSI C standard, but is included for information only. Microsoft-specific syntax is noted in comments following the syntax.


Definitions and Conventions

Terminals are endpoints in a syntax definition. No other resolution is possible. Terminals include the set of reserved words and user-defined identifiers.

Nonterminals are placeholders in the syntax and are defined elsewhere in this syntax summary. Definitions can be recursive.

An optional component is indicated by the subscripted opt. For example,

{ expression opt }

indicates an optional expression enclosed in curly braces.

The syntax conventions use different font attributes for different components of the syntax. The symbols and fonts are as follows:

Attribute | Description
nonterminal | Italic type indicates nonterminals.
const | Terminals in bold type are literal reserved words and symbols that must be entered as shown. Characters in this context are always case sensitive.
opt | Nonterminals followed by opt are always optional.
default typeface | Characters in the set described or listed in this typeface can be used as terminals in C statements.

A colon (:) following a nonterminal introduces its definition. Alternative definitions are listed on separate lines, except when prefaced with the words “one of.”


Lexical Grammar

  • Tokens

  • Keywords

  • Identifiers

  • Constants

  • String Literals

  • Operators

  • Punctuators


Summary of Tokens

token :

keyword
identifier
constant
string-literal
operator
punctuator

preprocessing-token :

header-name
identifier
pp-number
character-constant
string-literal
operator
punctuator
each nonwhite-space character that cannot be one of the above

header-name :

< path-spec >
"path spec"

path-spec :

Legal file path

pp-number :

digit
. digit
pp-number digit
pp-number nondigit
pp-number e sign
pp-number E sign
pp-number .


Summary of Keywords

keyword : one of

auto | double | int | struct
break | else | long | switch
case | enum | register | typedef
char | extern | return | union
const | float | short | unsigned
continue | for | signed | void
default | goto | sizeof | volatile
do | if | static | while


Summary of Identifiers

identifier :

nondigit
identifier nondigit
identifier digit

nondigit : one of

_ a b c d e f g h i j k l m
n o p q r s t u v w x y z
A B C D E F G H I J K L M
N O P Q R S T U V W X Y Z

digit : one of

0 1 2 3 4 5 6 7 8 9


Summary of Constants

constant :

floating-point-constant
integer-constant
enumeration-constant
character-constant

floating-point-constant :

fractional-constant exponent-part opt floating-suffix opt
digit-sequence exponent-part floating-suffix opt

fractional-constant :

digit-sequence opt . digit-sequence
digit-sequence .

exponent-part :

e sign opt digit-sequence
E sign opt digit-sequence

sign : one of

+ –

digit-sequence :

digit
digit-sequence digit

floating-suffix : one of

f l F L

integer-constant :

decimal-constant integer-suffix opt
octal-constant integer-suffix opt
hexadecimal-constant integer-suffix opt

decimal-constant :

nonzero-digit
decimal-constant digit

octal-constant :

0
octal-constant octal-digit

hexadecimal-constant :

0x hexadecimal-digit
0X hexadecimal-digit
hexadecimal-constant hexadecimal-digit

nonzero-digit : one of

1 2 3 4 5 6 7 8 9

octal-digit : one of

0 1 2 3 4 5 6 7

hexadecimal-digit : one of

0 1 2 3 4 5 6 7 8 9
a b c d e f
A B C D E F

unsigned-suffix : one of

u U

long-suffix : one of

l L

character-constant :

'c-char-sequence'
L'c-char-sequence'

integer-suffix :

unsigned-suffix long-suffix opt
long-suffix unsigned-suffix opt

c-char-sequence :

c-char
c-char-sequence c-char

c-char :

Any member of the source character set except the single quotation mark ('), backslash (\), or newline character
escape-sequence

escape-sequence :

simple-escape-sequence
octal-escape-sequence
hexadecimal-escape-sequence

simple-escape-sequence : one of

\a \b \f \n \r \t \v
\' \" \\ \?

octal-escape-sequence :

\ octal-digit
\ octal-digit octal-digit
\ octal-digit octal-digit octal-digit

hexadecimal-escape-sequence :

\x hexadecimal-digit
hexadecimal-escape-sequence hexadecimal-digit


Summary of String Literals

string-literal :

"s-char-sequence opt"
L"s-char-sequence opt"

s-char-sequence :

s-char
s-char-sequence s-char

s-char :

any member of the source character set except the double-quotation mark ("), backslash (\), or newline character
escape-sequence


Operators

operator : one of

[ ] ( ) . –>
++ –– & * + – ~ ! sizeof
/ % << >> < > <= >= == != ^ | && !!
? :
= *= /= %= += –= <<= >>= &= ^= |=
, # ##

assignment-operator : one of

= *= /= %= += –= <<= >>= &= ^= |=


Punctuators

punctuator : one of

[ ] ( ) { } * , : = ; ... #


Phrase Structure Grammar

  • Expressions

  • Declarations

  • Statements

  • External Definitions


Summary of Expressions

primary-expression :

identifier
constant
string-literal
( expression )

expression :

assignment-expression
expression , assignment-expression

constant-expression :

conditional-expression

conditional-expression :

logical-OR-expression
logical-OR-expression ? expression : conditional-expression

assignment-expression :

conditional-expression
unary-expression assignment-operator assignment-expression

postfix-expression :

primary-expression
postfix-expression [ expression ]
postfix-expression ( argument-expression-list opt )
postfix-expression . identifier
postfix-expression –> identifier
postfix-expression ++
postfix-expression ––

argument-expression-list :

assignment-expression
argument-expression-list , assignment-expression

unary-expression :

postfix-expression
++ unary-expression
–– unary-expression
unary-operator cast-expression
sizeof unary-expression
sizeof ( type-name )

unary-operator : one of

& * + – ~ !

cast-expression :

unary-expression
( type-name ) cast-expression

multiplicative-expression :

cast-expression
multiplicative-expression * cast-expression
multiplicative-expression / cast-expression
multiplicative-expression % cast-expression

additive-expression :

multiplicative-expression
additive-expression + multiplicative-expression
additive-expression – multiplicative-expression

shift-expression :

additive-expression
shift-expression << additive-expression
shift-expression >> additive-expression

relational-expression :

shift-expression
relational-expression < shift-expression
relational-expression > shift-expression
relational-expression <= shift-expression
relational-expression >= shift-expression

equality-expression :

relational-expression
equality-expression == relational-expression
equality-expression != relational-expression

AND-expression :

equality-expression
AND-expression & equality-expression

exclusive-OR-expression :

AND-expression
exclusive-OR-expression ^ AND-expression

inclusive-OR-expression :

exclusive-OR-expression
inclusive-OR-expression | exclusive-OR-expression

logical-AND-expression :

inclusive-OR-expression
logical-AND-expression && inclusive-OR-expression

logical-OR-expression :

logical-AND-expression
logical-OR-expression || logical-AND-expression


Summary of Declarations

declaration :

declaration-specifiers attribute-seq opt init-declarator-list opt ;
/* attribute-seq is Microsoft Specific */

declaration-specifiers :

storage-class-specifier declaration-specifiers opt
type-specifier declaration-specifiers opt
type-qualifier declaration-specifiers opt

attribute-seq : /* attribute-seq is Microsoft Specific */

attribute attribute-seq opt
attribute : one of /* Microsoft Specific */

__asm | __fastcall
__based | __inline
__cdecl | __stdcall

init-declarator-list :

init-declarator
init-declarator-list , init-declarator

init-declarator :

declarator
declarator = initializer /* For scalar initialization */

storage-class-specifier :

auto
register
static
extern
typedef
__declspec ( extended-decl-modifier-seq ) /* Microsoft Specific */

type-specifier :

void
char
short
int
__int8 /* Microsoft Specific */
__int16 /* Microsoft Specific */
__int32 /* Microsoft Specific */
__int64 /* Microsoft Specific */
long
float
double
signed
unsigned
struct-or-union-specifier
enum-specifier
typedef-name

type-qualifier :

const
volatile

declarator :

pointer opt direct-declarator

direct-declarator :

identifier
( declarator )
direct-declarator [ constant-expression opt]
direct-declarator ( parameter-type-list ) /* New-style declarator */
direct-declarator ( identifier-list opt ) /* Obsolete-style declarator */

pointer :

* type-qualifier-list opt
* type-qualifier-list opt pointer

parameter-type-list : /* The parameter list */

parameter-list
parameter-list , ...

parameter-list :

parameter-declaration
parameter-list , parameter-declaration

type-qualifier-list :

type-qualifier
type-qualifier-list type-qualifier

enum-specifier :

enum identifier opt { enumerator-list }
enum identifier

enumerator-list :

enumerator
enumerator-list , enumerator

enumerator :

enumeration-constant
enumeration-constant = constant-expression

enumeration-constant :

identifier

struct-or-union-specifier :

struct-or-union identifier opt { struct-declaration-list }
struct-or-union identifier

struct-or-union :

struct
union

struct-declaration-list :

struct-declaration
struct-declaration-list struct-declaration

struct-declaration :

specifier-qualifier-list struct-declarator-list ;

specifier-qualifier-list :

type-specifier specifier-qualifier-list opt
type-qualifier specifier-qualifier-list opt

struct-declarator-list :

struct-declarator
struct-declarator-list , struct-declarator

struct-declarator :

declarator
type-specifier declarator opt : constant-expression

parameter-declaration :

declaration-specifiers declarator /* Named declarator */
declaration-specifiers abstract-declarator opt /* Anonymous declarator */

identifier-list : /* For old-style declarator */

identifier
identifier-list , identifier

abstract-declarator : /* Used with anonymous declarators */

pointer
pointer opt direct-abstract-declarator

direct-abstract-declarator :

( abstract-declarator )
direct-abstract-declarator opt [ constant-expression opt ]
direct-abstract-declarator opt ( parameter-type-list opt )

initializer :

assignment-expression
{ initializer-list } /* For aggregate initialization */
{ initializer-list , }

initializer-list :

initializer
initializer-list , initializer

type-name :

specifier-qualifier-list abstract-declarator opt

typedef-name :

identifier

extended-decl-modifier-seq :/* Microsoft Specific */

extended-decl-modifier opt
extended-decl-modifier-seq extended-decl-modifier

extended-decl-modifier : /* Microsoft Specific */

thread
naked
dllimport
dllexport


Summary of Statements

statement :

labeled-statement
compound-statement
expression-statement
selection-statement
iteration-statement
jump-statement
try-except-statement /* Microsoft Specific */
try-finally-statement /* Microsoft Specific */

jump-statement :

goto identifier ;
continue;
break;
return expression opt ;

compound-statement :

{ declaration-list opt statement-list opt }

declaration-list :

declaration
declaration-list declaration

statement-list :

statement
statement-list statement

expression-statement :

expression opt ;

iteration-statement :

while ( expression ) statement
do statement while ( expression );
for ( expression opt ; expression opt ; expression opt ) statement

selection-statement :

if ( expression ) statement
if ( expression ) statement else statement
switch ( expression ) statement

labeled-statement :

identifier : statement
case constant-expression : statement
default : statement

try-except-statement : /* Microsoft Specific */

__try compound-statement
__except ( expression ) compound-statement

try-finally-statement : /* Microsoft Specific */

__try compound-statement
__finally compound-statement


External Definitions

translation-unit :

external-declaration
translation-unit external-declaration

external-declaration : /* Allowed only at external (file) scope */

function-definition
declaration

function-definition : /* Declarator here is the function declarator */

declaration-specifiers opt declarator declaration-list opt compound-statement


Implementation-Defined Behavior

ANSI X3.159-1989, American National Standard for Information Systems – Programming Language – C, contains an appendix called “Portability Issues.” The ANSI appendix lists areas of the C language that ANSI leaves open to each particular implementation. This appendix describes how Microsoft C handles these implementation-defined areas of the C language.

This appendix follows the same order as the ANSI appendix. Each item covered includes references to the ANSI chapter and section that explains the implementation-defined behavior.

Note This appendix describes the U.S. English-language version of the C compiler only. Implementations of Microsoft C for other languages may differ slightly.


Translation: Diagnostics

ANSI 2.1.1.3 How a diagnostic is identified

Microsoft C produces error messages in the form:

filename( line-number ) : diagnostic Cnumber message

where filename is the name of the source file in which the error was encountered; line-number is the line number at which the compiler detected the error; diagnostic is either “error” or “warning”; number is a unique four-digit number (preceded by a C, as noted in the syntax) that identifies the error or warning; message is an explanatory message.


Environment

  • Arguments to main

  • Interactive Devices


Arguments to main

ANSI 2.1.2.2.1 The semantics of the arguments to main

In Microsoft C, the function called at program startup is called main. There is no prototype declared for main, and it can be defined with zero, two, or three parameters:

int main( void )
int main( int argc, char *argv[] )
int main( int argc, char *argv[], char *envp[] )

The third line above, where main accepts three parameters, is a Microsoft extension to the ANSI C standard. The third parameter, envp, is an array of pointers to environment variables. The envp array is terminated by a null pointer. See The main Function and Program Execution in Chapter 2 for more information about main and envp.

The variable argc never holds a negative value.

The array of strings ends with argv[argc], which contains a null pointer.

All elements of the argv array are pointers to strings.

A program invoked with no command-line arguments will receive a value of one for argc, as the name of the executable file is placed in argv[0]. (In MS-DOS versions prior to 3.0, the executable-file name is not available. The letter “C” is placed in argv[0].) Strings pointed to by argv[1] through argv[argc – 1] represent program parameters.

The parameters argc and argv are modifiable and retain their last-stored values between program startup and program termination.


Interactive Devices

ANSI 2.1.2.3 What constitutes an interactive device

Microsoft C defines the keyboard and the display as interactive devices.


Behavior of Identifiers

  • Significant Characters Without External Linkage

  • Significant Characters with External Linkage

  • Uppercase and Lowercase


Significant Characters Without External Linkage

ANSI 3.1.2 The number of significant characters without external linkage

Identifiers are significant to 247 characters. The compiler does not restrict the number of characters you can use in an identifier; it simply ignores any characters beyond the limit.


Significant Characters with External Linkage

ANSI 3.1.2 The number of significant characters with external linkage

Identifiers declared extern in programs compiled with Microsoft C are significant to 247 characters. You can modify this default to a smaller number using the /H (restrict length of external names) option.


Uppercase and Lowercase

ANSI 3.1.2 Whether case distinctions are significant

Microsoft C treats identifiers within a compilation unit as case sensitive.

The Microsoft linker is case sensitive. You must specify all identifiers consistently according to case.


Characters

  • The ASCII Character Set

  • Multibyte Characters

  • Bits per Character

  • Character Sets

  • Unrepresented Character Constants

  • Wide Characters

  • Converting Multibyte Characters

  • Range of char Values


The ASCII Character Set

ANSI 2.2.1 Members of source and execution character sets

The source character set is the set of legal characters that can appear in source files. For Microsoft C, the source character set is the standard ASCII character set.

! WARNING Because keyboard and console drivers can remap the character set, programs intended for international distribution should check the country code.


Multibyte Characters

ANSI 2.2.1.2 Shift states for multibyte characters

Multibyte characters are used by some implementations, including Microsoft C, to represent foreign-language characters not represented in the base character set. However, Microsoft C does not support any state-dependent encodings. Therefore, there are no shift states. See Multibyte and Wide Characters in Chapter 1 for more information.


Bits per Character

ANSI 2.2.4.2.1 Number of bits in a character

The number of bits in a character is represented by the manifest constant CHAR_BIT. The LIMITS.H file defines CHAR_BIT as 8.


Character Sets

ANSI 3.1.3.4 Mapping members of the source character set

The source character set and execution character set include the ASCII characters listed in Table B.1. Escape sequences are also shown in the table.

Table B.1 Escape Sequences

Escape Sequence | Character | ASCII Value
\a | Alert/bell | 7
\b | Backspace | 8
\f | Formfeed | 12
\n | Newline | 10
\r | Carriage return | 13
\t | Horizontal tab | 9
\v | Vertical tab | 11
\" | Double quotation | 34
\' | Single quotation | 39
\\ | Backslash | 92


Unrepresented Character Constants

ANSI 3.1.3.4 The value of an integer character constant that contains a character or escape sequence not represented in the basic execution character set or the extended character set for a wide character constant

All character constants or escape sequences can be represented in the extended character set.


Wide Characters

ANSI 3.1.3.4 The value of an integer character constant that contains more than one character or a wide character constant that contains more than one multibyte character

The regular character constant, 'ab' has the integer value (int)0x6162. When there is more than one byte, previously read bytes are shifted left by the value of CHAR_BIT and the next byte is compared using the bitwise-OR operator with the low CHAR_BIT bits. The number of bytes in the multibyte character constant cannot exceed sizeof(int), which is 4 for 32-bit target code.

The multibyte character constant is read as above and this is converted to a wide-character constant using the mbtowc run-time function. If the result is not a valid wide-character constant, an error is issued. In any event, the number of bytes examined by the mbtowc function is limited to the value of MB_CUR_MAX.


Converting Multibyte Characters

ANSI 3.1.3.4 The current locale used to convert multibyte characters into corresponding wide characters (codes) for a wide character constant

The current locale is the “C” locale by default. It can be changed with the setlocale library routine. The LC_CTYPE category of the current locale sets the current working code page, which determines correspondence and conversion between the multibyte and wide-character sets. The mbstowcs, wcstombs, mbtowc, and wctomb library routines provide direct mappings between the multibyte and wide-character sets. Also, many of the stream routines, such as the print, scan, get, and put families, automatically provide mappings between these two character sets.


Range of char Values

ANSI 3.2.1.1 Whether a “plain” char has the same range of values as a signed char or an unsigned char

All signed character values range from –128 to 127. All unsigned character values range from 0 to 255.

The /J compiler option changes the default from signed to unsigned.


Integers

  • Range of Integer Values

  • Demotion of Integers

  • Signed Bitwise Operations

  • Remainders

  • Right Shifts


Range of Integer Values

ANSI 3.1.2.5 The representations and sets of values of the various types of integers

Integers contain 32 bits (four bytes). Signed integers are represented in two’s-complement form. The most-significant bit holds the sign: 1 for negative, 0 for positive and zero. The values are listed below:

Type | Minimum and Maximum
unsigned short | 0 to 65535
signed short | –32768 to 32767
unsigned long | 0 to 4294967295
signed long | –2147483648 to 2147483647


Demotion of Integers

ANSI 3.2.1.2 The result of converting an integer to a shorter signed integer, or the result of converting an unsigned integer to a signed integer of equal length, if the value cannot be represented

When a long integer is cast to a short, or a short is cast to a char, the least-significant bytes are retained.

For example, this line

short x = (short)0x12345678L;

assigns the value 0x5678 to x, and this line

char y = (char)0x1234;

assigns the value 0x34 to y.

When signed variables are converted to unsigned and vice versa, the bit patterns remain the same. For example, casting –2 (0xFE) to an unsigned value yields 254 (also 0xFE).


Signed Bitwise Operations

ANSI 3.3 The results of bitwise operations on signed integers

Bitwise operations on signed integers work the same as bitwise operations on unsigned integers. For example, –16 & 99 can be expressed in binary as

  11111111 11110000
& 00000000 01100011
  _________________
  00000000 01100000

The result of the bitwise AND is 96.


Remainders

ANSI 3.3.5 The sign of the remainder on integer division

The sign of the remainder is the same as the sign of the dividend. For example,

 50 / -6 == -8
 50 % -6 ==  2
-50 /  6 == -8
-50 %  6 == -2


Right Shifts

ANSI 3.3.7 The result of a right shift of a negative-value signed integral type

Shifting a negative value to the right yields half the absolute value, rounded down. For example, –253 (binary 11111111 00000011) shifted right one bit produces –127 (binary 11111111 10000001). A positive 253 shifts right to produce +126.

Right shifts preserve the sign bit. When a signed integer shifts right, the most-significant bit remains set. When an unsigned integer shifts right, the most-significant bit is cleared.

If 0xF000 is unsigned, the result is 0x7800.

If 0xF0000000 is signed, a right shift produces 0xF8000000. Shifting a positive number right 32 times produces 0xF0000000. Shifting a negative number right 32 times produces 0xFFFFFFFF.


Floating-Point Math

  • Values

  • Casting Integers to Floating-Point Values

  • Truncation of Floating-Point Values


Values

ANSI 3.1.2.5 The representations and sets of values of the various types of floating-point numbers

The float type contains 32 bits: 1 for the sign, 8 for the exponent, and 23 for the mantissa. Its range is +/– 3.4E38 with at least 7 digits of precision.

The double type contains 64 bits: 1 for the sign, 11 for the exponent, and 52 for the mantissa. Its range is +/– 1.7E308 with at least 15 digits of precision.

The long double type contains 80 bits: 1 for the sign, 15 for the exponent, and 64 for the mantissa. Its range is +/– 1.2E4932 with at least 19 digits of precision. With the Microsoft C compiler, the representation of type long double is identical to type double.


Casting Integers to Floating-Point Values

ANSI 3.2.1.3 The direction of truncation when an integral number is converted to a floating-point number that cannot exactly represent the original value

When an integral number is cast to a floating-point value that cannot exactly represent the value, the value is rounded (up or down) to the nearest suitable value.

For example, casting an unsigned long (with 32 bits of precision) to a float (whose mantissa has 23 bits of precision) rounds the number to the nearest multiple of 256. The long values 4,294,966,913 to 4,294,967,167 are all rounded to the float value 4,294,967,040.


Truncation of Floating-Point Values

ANSI 3.2.1.4 The direction of truncation or rounding when a floating-point number is converted to a narrower floating-point number

When an underflow occurs, the value of a floating-point variable is rounded down to zero. An overflow may cause a run-time error or it may produce an unpredictable value, depending on the optimizations specified.


Arrays and Pointers

  • Largest Array Size

  • Pointer Subtraction


Largest Array Size

ANSI 3.3.3.4, 4.1.1 The type of integer required to hold the maximum size of an array—that is, the size of size_t

The size_t typedef is an unsigned int with the range 0x00000000 to 0x7CFFFFFF.


Pointer Subtraction

ANSI 3.3.6, 4.1.1 The type of integer required to hold the difference between two pointers to elements of the same array, ptrdiff_t

A ptrdiff_t is a signed int in the range –4,294,967,296 to 4,294,967,295.


Registers: Availability of Registers

ANSI 3.5.1 The extent to which objects can actually be placed in registers by use of the register storage-class specifier

The 32-bit compiler does not honor user requests for register variables. Instead, it makes it own choices when optimizing.


Structures, Unions, Enumerations, and Bit Fields

  • Improper Access to a Union

  • Padding and Alignment of Structure Members

  • Sign of Bit Fields

  • Storage of Bit Fields

  • The enum Type


Improper Access to a Union

ANSI 3.3.2.3 A member of a union object is accessed using a member of a different type

If a union of two types is declared and one value is stored, but the union is accessed with the other type, the results are unreliable.

For example, a union of float and int is declared. A float value is stored, but the program later accesses the value as an int. In such a situation, the value would depend on the internal storage of float values. The integer value would not be reliable.


Padding and Alignment of Structure Members

ANSI 3.5.2.1 The padding and alignment of members of structures and whether a bit field can straddle a storage-unit boundary

Structure members are stored sequentially in the order in which they are declared: the first member has the lowest memory address and the last member the highest.

Every data object has an alignment-requirement. The alignment-requirement for all data except structures, unions, and arrays is either the size of the object or the current packing size (specified with either /Zp or the pack pragma, whichever is less). For structures, unions, and arrays, the alignment-requirement is the largest alignment-requirement of its members. Every object is allocated an offset so that

offset % alignment-requirement == 0

Adjacent bit fields are packed into the same 1-, 2-, or 4-byte allocation unit if the integral types are the same size and if the next bit field fits into the current allocation unit without crossing the boundary imposed by the common alignment requirements of the bit fields.


Sign of Bit Fields

ANSI 3.5.2.1 Whether a “plain” int field is treated as a signed int bit field or as an unsigned int bit field

Bit fields can be signed or unsigned. Plain bit fields are treated as signed.


Storage of Bit Fields

ANSI 3.5.2.1 The order of allocation of bit fields within an int

Bit fields are allocated within an integer from least-significant to most-significant bit. In the following code

struct mybitfields
{
   unsigned a : 4;
   unsigned b : 5;
   unsigned c : 7;
} test;

void main( void )
{
   test.a = 2;
   test.b = 31;
   test.c = 0;
}

the bits would be arranged as follows:

00000001 11110010
cccccccb bbbbaaaa

Since the 80x86 processors store the low byte of integer values before the high byte, the integer 0x01F2 above would be stored in physical memory as 0xF2 followed by 0x01.


The enum type

ANSI 3.5.2.2 The integer type chosen to represent the values of an enumeration type

A variable declared as enum is an int.


Qualifiers: Access to Volatile Objects

ANSI 3.5.5.3 What constitutes an access to an object that has volatile-qualified type

Any reference to a volatile-qualified type is an access.


Declarators: Maximum number

ANSI 3.5.4 The maximum number of declarators that can modify an arithmetic, structure, or union type

Microsoft C does not limit the number of declarators. The number is limited only by available memory.


Statements: Limits on Switch Statements

ANSI 3.6.4.2 The maximum number of case values in a switch statement

Microsoft C does not limit the number of case values in a switch statement. The number is limited only by available memory.


Preprocessing Directives

  • Character Constants and Conditional Inclusion

  • Including Bracketed Filenames

  • Including Quoted Filenames

  • Character Sequences

  • Pragmas

  • Default Date and Time


Character Constants and Conditional Inclusion

ANSI 3.8.1 Whether the value of a single-character character constant in a constant expression that controls conditional inclusion matches the value of the same character constant in the execution character set. Whether such a character constant can have a negative value

The character set used in preprocessor statements is the same as the execution character set. The preprocessor recognizes negative character values.


Including Bracketed Filenames

ANSI 3.8.2 The method for locating includable source files

For file specifications enclosed in angle brackets, the preprocessor does not search directories of the parent files. A “parent” file is the file that has the #include directive in it. Instead, it begins by searching for the file in the directories specified on the compiler command line following /I. If the /I option is not present or fails, the preprocessor uses the INCLUDE environment variable to find any include files within angle brackets. The INCLUDE environment variable can contain multiple paths separated by semicolons (;). If more than one directory appears as part of the /I option or within the INCLUDE environment variable, the preprocessor searches them in the order in which they appear.


Including Quoted Filenames

ANSI 3.8.2 The support for quoted names for includable source files

If you specify a complete, unambiguous path specification for the include file between two sets of double quotation marks (" "), the preprocessor searches only that path specification and ignores the standard directories.

For include files specified as #include "path-spec", directory searching begins with the directories of the parent file, then proceeds through the directories of any grandparent files. Thus, searching begins relative to the directory containing the source file currently being processed. If there is no grandparent file and the file has not been found, the search continues as if the filename were enclosed in angle brackets.


Character Sequences

ANSI 3.8.2 The mapping of source file character sequences

Preprocessor statements use the same character set as source file statements with the exception that escape sequences are not supported.

Thus, to specify a path for an include file, use only one backslash:

#include "path1/path2/myfile"

Within source code, two backslashes are necessary:

fil = fopen( "path1\\path2\\myfile", "rt" );


Pragmas

ANSI 3.8.6 The behavior on each recognized #pragma directive

The following pragmas are defined for the Microsoft C compiler:

alloc_text | data_seg | include_alias | setlocale
auto_inline | function | intrinsic | warning
check_stack | hdrstop | message |
code_seg | inline_depth | optimize |
comment | inline_recursion | pack |


Default Date and Time

ANSI 3.8.8 The definitions for _DATE_ and _TIME_ when, respectively, the date and time of translation are not available

When the operating system does not provide the date and time of translation, the default values for _DATE_ and _TIME_ are May 03 1957 and 17:00:00".


Library Functions

  • NULL Macro

  • Diagnostic Printed by the assert Function

  • Character Testing

  • Domain Errors

  • Underflow of Floating-Point Values

  • The fmod Function

  • The signal Function

  • Default Signals

  • Terminating Newline Characters

  • Blank Lines

  • Null Characters

  • File Position in Append Mode

  • Truncation of Text Files

  • File Buffering

  • Zero-Length Files

  • Filenames

  • File Access Limits

  • Deleting Open Files

  • Renaming with a Name That Exists

  • Reading Pointer Values

  • Reading Ranges

  • File Position Errors

  • Messages Generated by the perror Function

  • Allocating Zero Memory

  • The abort Function

  • The atexit Function

  • Environment Names

  • The system Function

  • The strerror Function

  • The Time Zone

  • The clock Function


NULL Macro

ANSI 4.1.5 The null pointer constant to which the macro NULL expands

Several include files define the NULL macro as ((void *)0).


Diagnostic Printed by the assert Function

ANSI 4.2 The diagnostic printed by and the termination behavior of the assert function

The assert function prints a diagnostic message and calls the abort routine if the expression is false (0). The diagnostic message has the form

Assertion failed: expression, file filename, line linenumber

where filename is the name of the source file and linenumber is the line number of the assertion that failed in the source file. No action is taken if expression is true (nonzero).


Character Testing

ANSI 4.3.1 The sets of characters tested for by the isalnum, isalpha, iscntrl, islower, isprint, and isupper functions

The following list describes these functions as they are implemented by the Microsoft C compiler.

Function | Tests For
isalnum | Characters 0 – 9, A–Z, a–z ASCII 48–57, 65–90, 97–122
isalpha | Characters A–Z, a–z ASCII 65–90, 97–122
iscntrl | ASCII 0 –31, 127
islower | Characters a–z ASCII 97–122
isprint | Characters A–Z, a–z, 0 – 9, punctuation, space ASCII 32–126
isupper | Characters A–Z ASCII 65–90


Domain Errors

ANSI 4.5.1 The values returned by the mathematics functions on domain errors

The ERRNO.H file defines the domain error constant EDOM as 33.


Underflow of Floating-Point Values

ANSI 4.5.1 Whether the mathematics functions set the integer expression errno to the value of the macro ERANGE on underflow range errors

A floating-point underflow does not set the expression errno to ERANGE. When a value approaches zero and eventually underflows, the value is set to zero.


The fmod Function

ANSI 4.5.6.4 Whether a domain error occurs or zero is returned when the fmod function has a second argument of zero

When the fmod function has a second argument of zero, the function returns zero.


The signal Function

ANSI 4.7.1.1 The set of signals for the signal function

The first argument passed to signal must be one of the symbolic constants described in the Run-Time Library Reference for the signal function. The information in the Run-Time Library Reference also lists the operating mode support for each signal. The constants are also defined in SIGNAL.H.


Default Signals

ANSI 4.7.1.1 If the equivalent of signal (sig, SIG_DFL) is not executed prior to the call of a signal handler, the blocking of the signal that is performed

Signals are set to their default status when a program begins running.


Terminating Newline Characters

ANSI 4.9.2 Whether the last line of a text stream requires a terminating newline character

Stream functions recognize either new line or end of file as the terminating character for a line.


Blank Lines

ANSI 4.9.2 Whether space characters that are written out to a text stream immediately before a newline character appear when read in

Space characters are preserved.


Null Characters

ANSI 4.9.2 The number of null characters that can be appended to data written to a binary stream

Any number of null characters can be appended to a binary stream.


File Position in Append Mode

ANSI 4.9.3 Whether the file position indicator of an append mode stream is initially positioned at the beginning or end of the file

When a file is opened in append mode, the file-position indicator initially points to the end of the file.


Truncation of Text Files

ANSI 4.9.3 Whether a write on a text stream causes the associated file to be truncated beyond that point

Writing to a text stream does not truncate the file beyond that point.


File Buffering

ANSI 4.9.3 The characteristics of file buffering

Disk files accessed through standard I/O functions are fully buffered. By default, the buffer holds 512 bytes.


Zero-Length Files

ANSI 4.9.3 Whether a zero-length file actually exists

Files with a length of zero are permitted.


Filenames

ANSI 4.9.3 The rules for composing valid file names

A file specification can include an optional drive letter (always followed by a colon), a series of optional directory names (separated by backslashes), and a filename.

Filenames and directory names can contain up to eight characters followed by a period and a three-character extension. Case is ignored. The wildcards * and ? are not permitted within the name or extension.


File Access Limits

ANSI 4.9.3 Whether the same file can be open multiple times

Opening a file that is already open is not permitted.


Deleting Open Files

ANSI 4.9.4.1 The effect of the remove function on an open file

The remove function deletes a file. If the file is open, this function fails and returns -1.


Renaming with a Name That Exists

ANSI 4.9.4.2 The effect if a file with the new name exists prior to a call to the rename function

If you attempt to rename a file using a name that exists, the rename function fails and returns an error code.


Reading Pointer Values

ANSI 4.9.6.2 The input for %p conversion in the fscanf function

When the %p format character is specified, the fscanf function converts pointers from hexadecimal ASCII values into the correct address.


Reading Ranges

ANSI 4.9.6.2 The interpretation of a dash (–) character that is neither the first nor the last character in the scanlist for % [ conversion in the fscanf function

The following line

fscanf( fileptr, "%[A-Z]", strptr);

reads any number of characters in the range A–Z into the string to which strptr points.


File Position Errors

ANSI 4.9.9.1, 4.9.9.4 The value to which the macro errno is set by the fgetpos or ftell function on failure

When fgetpos or ftell fails, errno is set to the manifest constant EINVAL if the position is invalid or EBADF if the file number is bad. The constants are defined in ERRNO.H.


Messages Generated by the perror Function

ANSI 4.9.10.4 The messages generated by the perror function

The perror function generates these messages:

0  Error 0
1
2  No such file or directory
3
4
5
6
7  Arg list too long
8  Exec format error
9  Bad file number
10
11
12 Not enough core
13 Permission denied
14
15
16
17 File exists
18 Cross-device link
19
20
21
22 Invalid argument
23
24 Too many open files
25
26
27
28 No space left on device
29
30
31
32
33 Math argument
34 Result too large
35
36 Resource deadlock would occur


Allocating Zero Memory

ANSI 4.10.3 The behavior of the calloc, malloc, or realloc function if the size requested is zero

The calloc, malloc, and realloc functions accept zero as an argument. No actual memory is allocated, but a valid pointer is returned and the memory block can be modified later by realloc.


The abort Function

ANSI 4.10.4.1 The behavior of the abort function with regard to open and temporary files

The abort function does not close files that are open or temporary. It does not flush stream buffers.


The atexit Function

ANSI 4.10.4.3 The status returned by the atexit function if the value of the argument is other than zero, EXIT_SUCCESS, or EXIT_FAILURE

The atexit function returns zero if successful, or a nonzero value if unsuccessful.


Environment Names

ANSI 4.10.4.4 The set of environment names and the method for altering the environment list used by the getenv function

The set of environment names is unlimited.

To change environment variables from within a C program, call the _putenv function. To change environment variables from the command line in Windows 95 or Windows NT, use the SET command (for example, SET LIB = D:\ LIBS).

Environment variables set from within a C program exist only as long as their host copy of the operating system command shell is running (CMD.EXE in Windows NT and COMMAND.COM in Windows 95). For example, the line

system( SET LIB = D:\LIBS );

would run a copy of the Windows NT command shell (CMD.EXE), set the environment variable LIB, and return to the C program, exiting the secondary copy of CMD.EXE. Exiting that copy of CMD.EXE removes the temporary environment variable LIB.

This example also runs on the Windows 95 platform.

Likewise, changes made by the _putenv function last only until the program ends.


The system Function

ANSI 4.10.4.5 The contents and mode of execution of the string by the system function

The system function executes an internal operating system command, or an .EXE, .COM (.CMD in Windows NT) or .BAT file from within a C program rather than from the command line.

The system function finds the command interpreter, which is typically CMD.EXE in the Windows NT operating system or COMMAND.COM in Windows 95. The system function then passes the argument string to the command interpreter.


The strerror Function

ANSI 4.11.6.2 The contents of the error message strings returned by the strerror function

The strerror function generates these messages:

0   Error 0
1
2   No such file or directory
3
4
5
6
7   Arg list too long
8   Exec format error
9   Bad file number
10
11
12  Not enough core
13  Permission denied
14
15
16
17  File exists
18  Cross-device link
19
20
21
22  Invalid argument
23
24  Too many open files
25
26
27
28  No space left on device
29
30
31
32
33  Math argument
34  Result too large
35
36  Resource deadlock would occur


The Time Zone

ANSI 4.12.1 The local time zone and Daylight Saving Time

The local time zone is Pacific Standard Time. Microsoft C supports Daylight Saving Time.


The clock Function

ANSI 4.12.2.1 The era for the clock function

The clock function’s era begins (with a value of 0) when the C program starts to execute. It returns times measured in 1/CLOCKS_PER_SEC (which equals 1/1000 for Microsoft C).


iostream Class Library Reference

Microsoft Visual C++ contains two versions of the C++ iostream class library, which supports object-oriented input and output. This library follows the syntax that the authors of the C++ language originally established and thus represents a de facto standard for C++ input and output. The other, newer version of the C++ iostream class library is found in the Standard C++ Library Reference section of this online documentation.
For information about iostream programming
iostream programming overview
About the iostream Documentation
Alphabetic Microsoft iostream class library reference

Interesting home pages
Visual C++ Home The entire Visual C++ product.


About the iostream Documentation

Chapter 1, iostream Programming, provides information you need to get started using iostream classes. After reading this material, you will begin to understand how to write programs that process formatted text character streams and binary disk files and how to customize the library in limited ways. The chapter includes advanced information on how to derive iostream classes and create custom multiparameter “manipulators.” These topics will get you started on extending the library and doing specialized formatting. You will also learn about the relationship between the iostream classes and their subsidiary buffer classes. You can then apply some of the iostream library design principles to your own class libraries.

Chapter 2, Alphabetic Microsoft iostream Class Library Reference, begins with a detailed class hierarchy diagram. The iostream class library reference follows, arranged by classes in alphabetic order. Each class description includes a summary of each member, arranged by category, followed by alphabetical listings of member functions (public and protected), overloaded operators, data members, and manipulators.

Public and protected class members are documented only when they are normally used in application programs or derived classes. See the class header files for a complete listing of class members.


iostream Programming

This chapter begins with a general description of the iostream classes and then describes output streams, input streams, and input/output streams. The end of the chapter provides information about advanced iostream programming.


What A Stream Is

Like C, C++ does not have built-in input/output capability. All C++ compilers, however, come bundled with a systematic, object-oriented I/O package, known as the iostream classes. The “stream” is the central concept of the iostream classes. You can think of a stream object as a “smart file” that acts as a source and destination for bytes. A stream’s characteristics are determined by its class and by customized insertion and extraction operators.

Through device drivers, the disk operating system deals with the keyboard, screen, printer, and communication ports as extended files. The iostream classes interact with these extended files. Built-in classes support reading from and writing to memory with syntax identical to that for disk I/O, which makes it easy to derive stream classes.


Input/Output Alternatives

This product provides several options for I/O programming:

  • C run-time library direct, unbuffered I/O

  • ANSI C run-time library stream I/O

  • Console and port direct I/O

  • The Microsoft Foundation Class Library

  • The Microsoft iostream Class Library

The iostream classes are useful for buffered, formatted text I/O. They are also useful for unbuffered or binary I/O if you need a C++ programming interface and decide not to use the Microsoft Foundation classes. The iostream classes are an object-oriented I/O alternative to the C run-time functions.

You can use iostream classes with the Microsoft® Windows® operating system. String and file streams work without restrictions, but the character-mode stream objects cin, cout, cerr, and clog are inconsistent with the Windows graphical user interface. You can also derive custom stream classes that interact directly with the Windows environment. If you link with the QuickWin library, however, the cin, cout, cerr, and clog objects are assigned to special windows because they are connected to the predefined files stdin, stdout, and stderr.

You cannot use iostream classes in tiny-model programs because tiny-model programs cannot contain static objects such as cin and cout.


The iostream Class Hierarchy

The class hierarchy diagram at the beginning of Chapter 2 shows some relationships between iostream classes. There are additional “member” relationships between the ios and streambuf families. Use the diagram to locate base classes that provide inherited member functions for derived classes.


Output Streams

An output stream object is a destination for bytes. The three most important output stream classes are ostream, ofstream, and ostrstream.

The ostream class, through the derived class ostream_withassign, supports the predefined stream objects:

  • cout standard output

  • cerr standard error with limited buffering

  • clog similar to cerr but with full buffering

Objects are rarely constructed from ostream or ostream_withassign; predefined objects are generally used. In some cases, you can reassign predefined objects after program startup. The ostream class, which can be configured for buffered or unbuffered operation, is best suited to sequential text-mode output. All functionality of the base class, ios, is included in ostream. If you construct an object of class ostream, you must specify a streambuf object to the constructor.

The ofstream class supports disk file output. If you need an output-only disk, construct an object of class ofstream. You can specify whether ofstream objects accept binary or text-mode data before or after opening the file. Many formatting options and member functions apply to ofstream objects, and all functionality of the base classes ios and ostream is included.

If you specify a filename in the constructor, that file is automatically opened when the object is constructed. Otherwise, you can use the open member function after invoking the default constructor, or you can construct an ofstream object based on an open file that is identified by a file descriptor.

Like the run-time function sprintf, the ostrstream class supports output to in-memory strings. To create a string in memory using I/O stream formatting, construct an object of class ostrstream. Because ostrstream objects are write-only, your program must access the resulting string through a pointer to char.


Constructing Output Stream Objects

If you use only the predefined cout, cerr, or clog objects, you don’t need to construct an output stream. You must use constructors for:

  • File streams

  • String streams

Output File Stream Constructors

You can construct an output file stream in one of three ways:

  • Use the default constructor, then call the open member function.
    ofstream myFile; // Static or on the stack
myFile.open( "filename", iosmode );

ofstream* pmyFile = new ofstream; // On the heap
pmyFile->open( "filename", iosmode );
  • Specify a filename and mode flags in the constructor call.
    ofstream myFile( "filename", iosmode );
  • Specify an integer file descriptor for a file already open for output. You can specify unbuffered output or a pointer to your own buffer.
    int fd = _open( "filename", dosmode );
ofstream myFile1( fd );  // Buffered mode (default)
ofstream myFile2( fd, NULL, 0 );  // Unbuffered mode ofstream
myFile3( fd, pch, buflen);  // User-supplied buffer

Output String Stream Constructors

To construct an output string stream, you can use one of two ostrstream constructors. One dynamically allocates its own storage, and the other requires the address and size of a preallocated buffer.

  • The dynamic constructor is used like this:
    char* sp;
ostrstream myString;
mystring << "this is a test" << ends;
sp = myString.str();  // Get a pointer to the string

    The ends “manipulator” adds the necessary terminating null character to the string.

  • The constructor that requires the preallocated buffer is used like this:
    char s[32];
ostrstream myString( s, sizeof( s ) );
myString << "this is a test" << ends; // Text stored in s


Using Insertion Operators and Controlling Format

This section shows how to control format and how to create insertion operators for your own classes. The insertion (<<) operator, which is preprogrammed for all standard C++ data types, sends bytes to an output stream object. Insertion operators work with predefined “manipulators,” which are elements that change the default format of integer arguments.

Output Width

To align output, you specify the output width for each item by placing the setw manipulator in the stream or by calling the width member function. This example right aligns the values in a column at least 10 characters wide:

#include <iostream.h>

void main()
{
   double values[] = { 1.23, 35.36, 653.7, 4358.24 };
   for( int i = 0; i < 4; i++ )
   {
      cout.width(10);
      cout << values[i] << '\n';
   }
}

The output looks like this:

      1.23
     35.36
     653.7
   4358.24

Leading blanks are added to any value fewer than 10 characters wide.

To pad a field, use the fill member function, which sets the value of the padding character for fields that have a specified width. The default is a blank. To pad the column of numbers with asterisks, modify the previous for loop as follows:

for( int i = 0; i < 4; i++ )
{
   cout.width( 10 );
   cout.fill( '*' );
   cout << values[i] << endl
}

The endl manipulator replaces the newline character ('\n'). The output looks like this:

******1.23
*****35.36
*****653.7
***4358.24

To specify widths for data elements in the same line, use the setw manipulator:

#include <iostream.h>
#include <iomanip.h>

void main()
{
   double values[] = { 1.23, 35.36, 653.7, 4358.24 };
   char *names[] = { "Zoot", "Jimmy", "Al", "Stan" };
   for( int i = 0; i < 4; i++ )
      cout << setw( 6 )  << names[i]
           << setw( 10 ) << values[i] << endl;
}

The width member function is declared in IOSTREAM.H. If you use setw or any other manipulator with arguments, you must include IOMANIP.H. In the output, strings are printed in a field of width 6 and integers in a field of width 10:

 Zoot       1.23
Jimmy      35.36
   Al      653.7
 Stan    4358.24

Neither setw nor width truncates values. If formatted output exceeds the width, the entire value prints, subject to the stream’s precision setting. Both setw and width affect the following field only. Field width reverts to its default behavior (the necessary width) after one field has been printed. However, the other stream format options remain in effect until changed.

Alignment

Output streams default to right-aligned text. To left align the names in the previous example and right align the numbers, replace the for loop as follows:

for ( int i = 0; i < 4; i++ )
   cout << setiosflags( ios::left )
        << setw( 6 )  << names[i]
        << resetiosflags( ios::left )
        << setw( 10 ) << values[i] << endl;

The output looks like this:

Zoot        1.23
Jimmy      35.36
Al         653.7
Stan     4358.24

The left-align flag is set by using the setiosflags manipulator with the ios::left enumerator. This enumerator is defined in the ios class, so its reference must include the ios:: prefix. The resetiosflags manipulator turns off the left-align flag. Unlike width and setw, the effect of setiosflags and resetiosflags is permanent.

Precision

The default value for floating-point precision is six. For example, the number 3466.9768 prints as 3466.98. To change the way this value prints, use the setprecision manipulator. The manipulator has two flags, ios::fixed and ios::scientific. If ios::fixed is set, the number prints as 3466.976800. If ios::scientific is set, it prints as 3.4669773+003.

To display the floating-point numbers shown in Alignment with one significant digit, replace the for loop as follows:

for ( int i = 0; i < 4; i++ )
   cout << setiosflags( ios::left )
        << setw( 6 )
        << names[i]
        << resetiosflags( ios::left )
        << setw( 10 )
        << setprecision( 1 )
        << values[i]
        << endl;

The program prints this list:

Zoot          1
Jimmy     4e+001
Al        7e+002
Stan      4e+003

To eliminate scientific notation, insert this statement before the for loop:

cout << setiosflags( ios::fixed );

With fixed notation, the program prints with one digit after the decimal point.

Zoot         1.2
Jimmy       35.4
Al         653.7
Stan      4358.2

If you change the ios::fixed flag to ios::scientific, the program prints this:

Zoot    1.2e+000
Jimmy   3.5e+001
Al      6.5e+002
Stan    4.4e+003

Again, the program prints one digit after the decimal point. If either ios::fixed or ios::scientific is set, the precision value determines the number of digits after the decimal point. If neither flag is set, the precision value determines the total number of significant digits. The resetiosflags manipulator clears these flags.

Radix

The dec, oct, and hex manipulators set the default radix for input and output. For example, if you insert the hex manipulator into the output stream, the object correctly translates the internal data representation of integers into a hexadecimal output format. The numbers are displayed with digits a through f in lowercase if the ios::uppercase flag is clear (the default); otherwise, they are displayed in uppercase. The default radix is dec (decimal).


Output File Stream Member Functions

Output stream member functions have three types: those that are equivalent to manipulators, those that perform unformatted write operations, and those that otherwise modify the stream state and have no equivalent manipulator or insertion operator. For sequential, formatted output, you might use only insertion operators and manipulators. For random-access binary disk output, you use other member functions, with or without insertion operators.

The open Function for Output Streams

To use an output file stream (ofstream), you must associate that stream with a specific disk file in the constructor or the open function. If you use the open function, you can reuse the same stream object with a series of files. In either case, the arguments describing the file are the same.

When you open the file associated with an output stream, you generally specify an open_mode flag. You can combine these flags, which are defined as enumerators in the ios class, with the bitwise OR ( | ) operator.

Flag | Function
ios::app | Opens an output file for appending.
ios::ate | Opens an existing file (either input or output) and seeks the end.
ios::in | Opens an input file. Use ios::in as an open_mode for an ofstream file to prevent truncating an existing file.
ios::out | Opens an output file. When you use ios::out for an ofstream object without ios::app, ios::ate, or ios::in, ios::trunc is implied.
ios::nocreate | Opens a file only if it already exists; otherwise the operation fails.
ios::noreplace | Opens a file only if it does not exist; otherwise the operation fails.
ios::trunc | Opens a file and deletes the old file (if it already exists).
ios::binary | Opens a file in binary mode (default is text mode).

Three common output stream situations involve mode options:

  • Creating a file. If the file already exists, the old version is deleted.
    ostream ofile( "FILENAME" );  // Default is ios::out
ofstream ofile( "FILENAME", ios::out ); // Equivalent to above
  • Appending records to an existing file or creating one if it does not exist.
    ofstream ofile( "FILENAME", ios::app );
  • Opening two files, one at a time, on the same stream.
    ofstream ofile();
ofile.open( "FILE1", ios::in );
// Do some output
ofile.close(); // FILE1 closed
ofile.open( "FILE2", ios::in );
// Do some more output
ofile.close(); // FILE2 closed
// When ofile goes out of scope it is destroyed.

The put Function

The put function writes one character to the output stream. The following two statements are the same by default, but the second is affected by the stream’s format arguments:

cout.put( 'A' ); // Exactly one character written
cout << 'A'; // Format arguments 'width' and 'fill' apply

The write Function

The write function writes a block of memory to an output file stream. The length argument specifies the number of bytes written. This example creates an output file stream and writes the binary value of the Date structure to it:

#include <fstream.h>

struct Date
{
   int mo, da, yr;
};

void main()
{
   Date dt = { 6, 10, 92 };
   ofstream tfile( "date.dat" , ios::binary );
   tfile.write( (char *) &dt, sizeof dt );
}

The write function does not stop when it reaches a null character, so the complete class structure is written. The function takes two arguments: a char pointer and a count of characters to write. Note the required cast to char* before the address of the structure object.

The seekp and tellp Functions

An output file stream keeps an internal pointer that points to the position where data is to be written next. The seekp member function sets this pointer and thus provides random-access disk file output. The tellp member function returns the file position. For examples that use the input stream equivalants to seekp and tellp, see The seekg and tellg Functions.

The close Function for Output Streams

The close member function closes the disk file associated with an output file stream. The file must be closed to complete all disk output. If necessary, the ofstream destructor closes the file for you, but you can use the close function if you need to open another file for the same stream object.

The output stream destructor automatically closes a stream’s file only if the constructor or the open member function opened the file. If you pass the constructor a file descriptor for an already-open file or use the attach member function, you must close the file explicitly.

Error Processing Functions

Use these member functions to test for errors while writing to a stream:

Function | Return value
bad | Returns TRUE if there is an unrecoverable error.
fail | Returns TRUE if there is an unrecoverable error or an “expected” condition, such as a conversion error, or if the file is not found. Processing can often resume after a call to clear with a zero argument.
good | Returns TRUE if there is no error condition (unrecoverable or otherwise) and the end-of-file flag is not set.
eof | Returns TRUE on the end-of-file condition.
clear | Sets the internal error state. If called with the default arguments, it clears all error bits.
rdstate | Returns the current error state. For a complete description of error bits, see the Class Library Reference.

The ! operator is overloaded to perform the same function as the fail function. Thus the expression

if( !cout)...

is equivalent to

if( cout.fail() )...

The void*() operator is overloaded to be the opposite of the ! operator; thus the expression

if( cout)...

is equal to

if( !cout.fail() )...

The void*() operator is not equivalent to good because it doesn’t test for the end of file.


The Effects of Buffering

The following example shows the effects of buffering. You might expect the program to print please wait, wait 5 seconds, and then proceed. It won’t necessarily work this way, however, because the output is buffered.

#include <iostream.h>
#include <time.h>

void main()
{
   time_t tm = time( NULL ) + 5;
   cout << "Please wait...";
   while ( time( NULL ) < tm )
      ;
   cout << "\nAll done" << endl;
}

To make the program work logically, the cout object must empty itself when the message is to appear. To flush an ostream object, send it the flush manipulator:

cout << "Please wait..." << flush;

This step flushes the buffer, ensuring the message prints before the wait. You can also use the endl manipulator, which flushes the buffer and outputs a carriage return–linefeed, or you can use the cin object. This object (with the cerr or clog objects) is usually tied to the cout object. Thus, any use of cin (or of the cerr or clog objects) flushes the cout object.


Binary Output Files

Streams were originally designed for text, so the default output mode is text. In text mode, the newline character (hexadecimal 10) expands to a carriage return–linefeed (16-bit only). The expansion can cause problems, as shown here:

#include <fstream.h>
int iarray[2] = { 99, 10 };
void main()
{
    ofstream os( "test.dat" );
    os.write( (char *) iarray, sizeof( iarray ) );
}

You might expect this program to output the byte sequence { 99, 0, 10, 0 }; instead, it outputs { 99, 0, 13, 10, 0 }, which causes problems for a program expecting binary input. If you need true binary output, in which characters are written untranslated, you have several choices:

  • Construct a stream as usual, then use the setmode member function, which changes the mode after the file is opened:
    ofstream ofs ( "test.dat" );
ofs.setmode( filebuf::binary );
ofs.write( char*iarray, 4 ); // Exactly 4 bytes written
  • Specify binary output by using the ofstream constuctor mode argument:
    #include <fstream.h>
#include <fcntl.h>
#include <io.h>
int iarray[2] = { 99, 10 };
void main()
{
    ofstream os( "test.dat", ios::binary );
    ofs.write( iarray, 4 ); // Exactly 4 bytes written
}
  • Use the binary manipulator instead of the setmode member function:
    ofs << binary;

    Use the text manipulator to switch the stream to text translation mode.

  • Open the file using the run-time _open function with a binary mode flag:
    filedesc fd = _open( "test.dat",
              _O_BINARY | _O_CREAT | _O_WRONLY );
ofstream ofs( fd );
ofs.write( ( char* ) iarray, 4 ); // Exactly 4 bytes written


Overloading the << Operator for Your Own Classes

Output streams use the insertion (<<) operator for standard types. You can also overload the << operator for your own classes.

The write function example showed the use of a Date structure. A date is an ideal candidate for a C++ class in which the data members (month, day, and year) are hidden from view. An output stream is the logical destination for displaying such a structure. This code displays a date using the cout object:

Date dt( 1, 2, 92 );
cout << dt;

To get cout to accept a Date object after the insertion operator, overload the insertion operator to recognize an ostream object on the left and a Date on the right. The overloaded << operator function must then be declared as a friend of class Date so it can access the private data within a Date object.

#include <iostream.h>

class Date
{
   int mo, da, yr;
public:
   Date( int m, int d, int y )
   {
      mo = m; da = d; yr = y;
   }
   friend ostream& operator<< ( ostream& os, Date& dt );
};

ostream& operator<< ( ostream& os, Date& dt )
{
   os << dt.mo << '/' << dt.da << '/' << dt.yr;
   return os;
}

void main()
{
   Date dt( 5, 6, 92 );
   cout << dt;
}

When you run this program, it prints the date:

5/6/92

The overloaded operator returns a reference to the original ostream object, which means you can combine insertions:

cout << "The date is" << dt << flush;


Writing Your Own Manipulators Without Arguments

Writing manipulators that don’t use arguments requires neither class derivation nor use of complex macros. Suppose your printer requires the pair <ESC>[ to enter bold mode. You can insert this pair directly into the stream:

cout << "regular " << '\033' << '[' << "boldface" << endl;

Or you can define the bold manipulator, which inserts the characters:

ostream& bold( ostream& os ) {
    return os << '\033' << '[';
}
cout << "regular " << bold << "boldface" << endl;

The globally defined bold function takes an ostream reference argument and returns the ostream reference. It is not a member function or a friend because it doesn’t need access to any private class elements. The bold function connects to the stream because the stream’s << operator is overloaded to accept that type of function, using a declaration that looks something like this:

ostream& ostream::operator<< ( ostream& (*_f)( ostream& ) ); {
    (*_f)( *this );
    return *this;
}

You can use this feature to extend other overloaded operators. In this case, it is incidental that bold inserts characters into the stream. The function is called when it is inserted into the stream, not necessarily when the adjacent characters are printed. Thus, printing could be delayed because of the stream’s buffering.


Input Streams

An input stream object is a source of bytes. The three most important input stream classes are istream, ifstream, and istrstream.

The istream class is best used for sequential text-mode input. You can configure objects of class istream for buffered or unbuffered operation. All functionality of the base class, ios, is included in istream. You will rarely construct objects from class istream. Instead, you will generally use the predefined cin object, which is actually an object of class istream_withassign. In some cases, you can assign cin to other stream objects after program startup.

The ifstream class supports disk file input. If you need an input-only disk file, construct an object of class ifstream. You can specify binary or text-mode data. If you specify a filename in the constructor, the file is automatically opened when the object is constructed. Otherwise, you can use the open function after invoking the default constructor. Many formatting options and member functions apply to ifstream objects. All functionality of the base classes ios and istream is included in ifstream.

Like the library function sscanf, the istrstream class supports input from in-memory strings. To extract data from a character array that has a null terminator, allocate and initialize the string, then construct an object of class istrstream.


Constructing Input Stream Objects

If you use only the cin object, you don’t need to construct an input stream. You must construct an input stream if you use:

  • File stream

  • String stream

Input File Stream Constructors

There are three ways to create an input file stream:

  • Use the void-argument constructor, then call the open member function:
    ifstream myFile; // On the stack
myFile.open( "filename", iosmode );

ifstream* pmyFile = new ifstream; // On the heap
pmyFile->open( "filename", iosmode );
  • Specify a filename and mode flags in the constructor invocation, thereby opening the file during the construction process:
    ifstream myFile( "filename", iosmode );
  • Specify an integer file descriptor for a file already open for input. In this case you can specify unbuffered input or a pointer to your own buffer:
    int fd = _open( "filename", dosmode );
ifstream myFile1( fd );  // Buffered mode (default)
ifstream myFile2( fd, NULL, 0 );  // Unbuffered mode
ifstream myFile3( fd, pch, buflen );  // User-supplied buffer

Input String Stream Constructors

Input string stream constructors require the address of preallocated, preinitialized storage:

char s[] = "123.45";
double amt;
istrstream myString( s );
myString >> amt; // Amt should contain 123.45


Using Extraction Operators

The extraction operator (>>), which is preprogrammed for all standard C++ data types, is the easiest way to get bytes from an input stream object.

Formatted text input extraction operators depend on white space to separate incoming data values. This is inconvenient when a text field contains multiple words or when commas separate numbers. In such a case, one alternative is to use the unformatted input member function getline to read a block of text with white space included, then parse the block with special functions. Another method is to derive an input stream class with a member function such as GetNextToken, which can call istream members to extract and format character data.


Testing for Extraction Errors

Output error processing functions, discussed in Error Processing Functions, apply to input streams. Testing for errors during extraction is important. Consider this statement:

cin >> n;

If n is a signed integer, a value greater than 32,767 (the maximum allowed value, or MAX_INT) sets the stream’s fail bit, and the cin object becomes unusable. All subsequent extractions result in an immediate return with no value stored.


Input Stream Manipulators

Many manipulators, such as setprecision, are defined for the ios class and thus apply to input streams. Few manipulators, however, actually affect input stream objects. Of those that do, the most important are the radix manipulators, dec, oct, and hex, which determine the conversion base used with numbers from the input stream.

On extraction, the hex manipulator enables processing of various input formats. For example, c, C, 0xc, 0xC, 0Xc, and 0XC are all interpreted as the decimal integer 12. Any character other than 0 through 9, A through F, a through f, x, and X terminates the numeric conversion. Thus the sequence "124n5" is converted to the number 124 with the ios::fail bit set.


Input Stream Member Functions

Input stream member functions are used for disk input. The member functions include:

  • The open Function

  • The get Function

  • The getline Function

  • The read Function

  • The seekg and tellg Functions

  • The close Function

The open Function for Input Streams

If you are using an input file stream (ifstream), you must associate that stream with a specific disk file. You can do this in the constructor, or you can use the open function. In either case, the arguments are the same.

You generally specify an open_mode flag when you open the file associated with an input stream (the default mode is ios::in). For a list of the open_mode flags, see The open Function. The flags can be combined with the bitwise OR ( | ) operator.

To read a file, first use the fail member function to determine whether it exists:

istream ifile( "FILENAME", ios::nocreate );
if ( ifile.fail() )
// The file does not exist ...

The get Function

The unformatted get member function works like the >> operator with two exceptions. First, the get function includes white-space characters, whereas the extractor excludes white space when the ios::skipws flag is set (the default). Second, the get function is less likely to cause a tied output stream (cout, for example) to be flushed.

A variation of the get function specifies a buffer address and the maximum number of characters to read. This is useful for limiting the number of characters sent to a specific variable, as this example shows:

#include <iostream.h>

void main()
{
   char line[25];
   cout << " Type a line terminated by carriage return\n>";
   cin.get( line, 25 );
   cout << ' ' << line;
}

In this example, you can type up to 24 characters and a terminating character. Any remaining characters can be extracted later.

The getline Function

The getline member function is similar to the get function. Both functions allow a third argument that specifies the terminating character for input. The default value is the newline character. Both functions reserve one character for the required terminating character. However, get leaves the terminating character in the stream and getline removes the terminating character.

The following example specifies a terminating character for the input stream:

#include <iostream.h>

void main()
{
   char line[100];
   cout << " Type a line terminated by 't'" << endl;
   cin.getline( line, 100, 't' );
   cout << line;
}

The read Function

The read member function reads bytes from a file to a specified area of memory. The length argument determines the number of bytes read. If you do not include that argument, reading stops when the physical end of file is reached or, in the case of a text-mode file, when an embedded EOF character is read.

This example reads a binary record from a payroll file into a structure:

#include <fstream.h>
#include <fcntl.h>
#include <io.h>

void main()
{
   struct
   {
      double salary;
      char name[23];
   } employee;

   ifstream is( "payroll", ios::binary | ios::nocreate );
   if( is ) {  // ios::operator void*()
      is.read( (char *) &employee, sizeof( employee ) );
      cout << employee.name << ' ' << employee.salary << endl;
   }
   else {
      cout << "ERROR: Cannot open file 'payroll'." << endl;
   }
}

The program assumes that the data records are formatted exactly as specified by the structure with no terminating carriage-return or linefeed characters.

The seekg and tellg Functions

Input file streams keep an internal pointer to the position in the file where data is to be read next. You set this pointer with the seekg function, as shown here:

#include <fstream.h>

void main()
{
   char ch;

   ifstream tfile( "payroll", ios::binary | ios::nocreate );
   if( tfile ) {
      tfile.seekg( 8 );      // Seek 8 bytes in (past salary)
      while ( tfile.good() ) { // EOF or failure stops the reading
         tfile.get( ch );
         if( !ch ) break; // quit on null
         cout << ch;
      }
   }
   else {
      cout << "ERROR: Cannot open file 'payroll'." << endl;
   }
}

To use seekg to implement record-oriented data management systems, multiply the fixed-length record size by the record number to obtain the byte position relative to the end of the file, then use the get object to read the record.

The tellg member function returns the current file position for reading. This value is of type streampos, a typedef defined in IOSTREAM.H. The following example reads a file and displays messages showing the positions of spaces.

#include <fstream.h>

void main()
{
   char ch;
ifstream tfile( "payroll", ios::binary | ios::nocreate );
   if( tfile ) {
       while ( tfile.good() ) {
          streampos here = tfile.tellg();
          tfile.get( ch );
          if ( ch == ' ' )
             cout << "\nPosition " << here << " is a space";
       }
   }
   else {
      cout << "ERROR: Cannot open file 'payroll'." << endl;
   }
}

The close Function for Input Streams

The close member function closes the disk file associated with an input file stream and frees the operating system file handle. The ifstream destructor closes the file for you (unless you called the attach function or passed your own file descriptor to the constructor), but you can use the close function if you need to open another file for the same stream object.


Overloading the >> Operator for Your Own Classes

Input streams use the extraction (>>) operator for the standard types. You can write similar extraction operators for your own types; your success depends on using white space precisely.

Here is an example of an extraction operator for the Date class presented earlier:

istream& operator>> ( istream& is, Date& dt )
{
   is >> dt.mo >> dt.da >> dt.yr;
   return is;
}


Input/Output Streams

An iostream object is a source and/or a destination for bytes. The two most important I/O stream classes, both derived from iostream, are fstream and strstream. These classes inherit the functionality of the istream and ostream classes described previously.

The fstream class supports disk file input and output. If you need to read from and write to a particular disk file in the same program, construct an fstream object. An fstream object is a single stream with two logical substreams, one for input and one for output. Although the underlying buffer contains separately designated positions for reading and writing, those positions are tied together.

The strstream class supports input and output of in-memory strings.


Custom Manipulators with Arguments

This section describes how to create output stream manipulators with one or more arguments, and how to use manipulators for non-output streams.

  • Output Stream Manipulators with One Argument (int or long)

  • Other One-Argument Output Stream Manipulators

  • Output Stream Manipulators with More Than One Argument

  • Custom Manipulators for Input and Input/Output Streams

  • Using Manipulators with Derived Stream Classes


Output Stream Manipulators with One Argument (int or long)

The iostream class library provides a set of macros for creating parameterized manipulators. Manipulators with a single int or long argument are a special case. To create an output stream manipulator that accepts a single int or long argument (like setw), you must use the OMANIP macro, which is defined in IOMANIP.H. This example defines a fillblank manipulator that inserts a specified number of blanks into the stream:

#include <iostream.h>
#include <iomanip.h>

ostream& fb( ostream& os, int l )
{
   for( int i=0; i < l; i++ )
        os << ' ';
   return os;
}

OMANIP(int) fillblank( int l )
{
   return OMANIP(int) ( fb, l );
}

void main()
{
    cout << "10 blanks follow" << fillblank( 10 ) << ".\n";
}

The IOMANIP.H header file contains a macro that expands OMANIP(int) into a class, __OMANIP_int, which includes a constructor and an overloaded ostream insertion operator for an object of the class. In the previous example, the fillblank function calls the __OMANIP_int constructor to return an object of class __OMANIP_int. Thus, fillblank can be used with an ostream insertion operator. The constructor calls the fb function. The expression OMANIP(long) expands to another built-in class, __OMANIP_long, which accommodates functions with a long integer argument.


Other One-Argument Output Stream Manipulators

To create manipulators that take arguments other than int and long, you must use the IOMANIPdeclare macro, which declares the classes for your new type, as well as the OMANIP macro.

The following example uses a class money, which is a long type. The setpic manipulator attaches a formatting “picture” string to the class that can be used by the overloaded stream insertion operator of the class money. The picture string is stored as a static variable in the money class rather than as data member of a stream class, so you do not have to derive a new output stream class.

#include <iostream.h>
#include <iomanip.h>
#include <string.h>

typedef char* charp;
IOMANIPdeclare( charp );

class money {
private:
    long value;
    static char *szCurrentPic;
public:
    money( long val ) { value = val; }
    friend ostream& operator << ( ostream& os, money m ) {
        // A more complete function would merge the picture
        // with the value rather than simply appending it
        os << m.value << '[' << money::szCurrentPic << ']';
        return os;
    }
    friend ostream& setpic( ostream& os, char* szPic ) {
        money::szCurrentPic = new char[strlen( szPic ) + 1];
        strcpy( money::szCurrentPic, szPic );
        return os;
    }
};
char *money::szCurrentPic;  // Static pointer to picture

OMANIP(charp) setpic(charp c)
{
    return OMANIP(charp) (setpic, c);
}

void main()
{
    money amt = 35235.22;
    cout << setiosflags( ios::fixed );
    cout << setpic( "###,###,###.##" ) << "amount = " << amt << endl;
}


Output Stream Manipulators with More Than One Argument

The following example shows how to write a manipulator, fill, to insert a specific number of a particular character. The manipulator, which takes two arguments, is similar to setpic in the previous example. The difference is that the character pointer type declaration is replaced by a structure declaration.

#include <iostream.h>
#include <iomanip.h>

struct fillpair {
       char ch;
        int  cch;
};

IOMANIPdeclare( fillpair );

ostream& fp( ostream& os, fillpair pair )
{
    for ( int c = 0; c < pair.cch; c++ ) {
        os << pair.ch;
    }
    return os;
}

OMANIP(fillpair) fill( char ch, int cch )
{
    fillpair pair;

    pair.cch = cch;
    pair.ch  = ch;
    return OMANIP (fillpair)( fp, pair );
}

void main()
{
    cout << "10 dots coming" << fill( '.', 10 ) << "done" << endl;
}

This example can be rewritten so that the manipulator definition is in a separate program file. In this case, the header file must contain these declarations:

struct fillpair {
       char ch;
       int  cch;
};
IOMANIPdeclare( fillpair );
ostream& fp( ostream& o, fillpair pair );
OMANIP(fillpair) fill( char ch, int cch );


Custom Manipulators for Input and Input/Output Streams

The OMANIP macro works with ostream and its derived classes. The SMANIP, IMANIP, and IOMANIP macros work with the classes ios, istream, and iostream, respectively.


Using Manipulators with Derived Stream Classes

Suppose you define a manipulator, xstream, that works with the ostream class. The manipulator will work with all classes derived from ostream. Further suppose you need manipulators that work only with xstream. In this case, you must add an overloaded insertion operator that is not a member of ostream:

xstream& operator<< ( xstream& xs, xstream& (*_f)( xstream& ) ) {
    (*_f)( xs );
    return xs;
}

The manipulator code looks like this:

xstream& bold( xstream& xs ) {
    return xs << '\033' << '[';
}

If the manipulator needs to access xstream protected data member functions, you can declare the bold function as a friend of the xstream class.


Deriving Your Own Stream Classes

Like any C++ class, a stream class can be derived to add new member functions, data members, or manipulators. If you need an input file stream that tokenizes its input data, for example, you can derive from the ifstream class. This derived class can include a member function that returns the next token by calling its base class’s public member functions or extractors. You may need new data members to hold the stream object’s state between operations, but you probably won’t need to use the base class’s protected member functions or data members.

For the straightforward stream class derivation, you need only write the necessary constructors and the new member functions.


The streambuf Class

Unless you plan to make major changes to the iostream library, you do not need to work much with the streambuf class, which does most of the work for the other stream classes. In most cases, you will create a modified output stream by deriving only a new streambuf class and connecting it to the ostream class.


Why Derive a Custom streambuf Class?

Existing output streams communicate to the file system and to in-memory strings. You can create streams that address a memory-mapped video screen, a window as defined by Microsoft Windows, a new physical device, and so on. A simpler method is to alter the byte stream as it goes to a file system device.


A streambuf Derivation Example

The following example modifies the cout object to print in two-column landscape (horizontal) mode on a printer that uses the PCL control language (for example, Hewlett-Packard LaserJet printer). As the test driver program shows, all member functions and manipulators that work with the original cout object work with the special version. The application programming interface is the same.

The example is divided into three source files:

  • HSTREAM.H — the LaserJet class declaration that must be included in the implementation file and application file

  • HSTREAM.CPP — the LaserJet class implementation that must be linked with the application

  • EXIOS204.CPP — the test driver program that sends output to a LaserJet printer

HSTREAM.H contains only the class declaration for hstreambuf, which is derived from the filebuf class and overrides the appropriate filebuf virtual functions.

// hstream.h - HP LaserJet output stream header
#include <fstream.h> // Accesses filebuf class
#include <string.h>
#include <stdio.h> // for sprintf

class hstreambuf : public filebuf
{
public:
    hstreambuf( int filed );
    virtual int sync();
    virtual int overflow( int ch );
    ~hstreambuf();
private:
    int column, line, page;
    char* buffer;
    void convert( long cnt );
    void newline( char*& pd, int& jj );
    void heading( char*& pd, int& jj );
    void pstring( char* ph, char*& pd, int& jj );
};
ostream& und( ostream& os );
ostream& reg( ostream& os );

HSTREAM.CPP contains the hstreambuf class implementation.

// hstream.cpp  - HP LaserJet output stream
#include "hstream.h"

const int REG  = 0x01;   // Regular font code
const int UND  = 0x02;   // Underline font code
const int CR   = 0x0d;   // Carriage return character
const int NL   = 0x0a;   // Newline character
const int FF   = 0x0c;   // Formfeed character
const int TAB  = 0x09;   // Tab character
const int LPP  = 57;     // Lines per page
const int TABW = 5;      // Tab width

// Prolog defines printer initialization (font, orientation, etc.
char prolog[] =
{ 0x1B, 0x45,                         // Reset printer
  0x1B, 0x28, 0x31, 0x30, 0x55,         // IBM PC char set
  0x1B, 0x26, 0x6C, 0x31, 0x4F,         // Landscape
  0x1B, 0x26, 0x6C, 0x38, 0x44,       // 8 lines per inch
  0x1B, 0x26, 0x6B, 0x32, 0x53};        // Lineprinter font

// Epilog prints the final page and terminates the output
char epilog[] = { 0x0C, 0x1B, 0x45 };   // Formfeed, reset

char uon[] = { 0x1B, 0x26, 0x64, 0x44, 0 }; // Underline on
char uoff[] = { 0x1B, 0x26, 0x64, 0x40, 0 };// Underline off

hstreambuf::hstreambuf( int filed ) : filebuf( filed )
{
    column = line = page = 0;
    int size = sizeof( prolog );
    setp( prolog, prolog + size );
    pbump( size );   // Puts the prolog in the put area
    filebuf::sync(); // Sends the prolog to the output file
    buffer = new char[1024]; // Allocates destination buffer
}

hstreambuf::~hstreambuf()
{
    sync(); // Makes sure the current buffer is empty
    delete buffer; // Frees the memory
    int size = sizeof( epilog );
    setp( epilog, epilog + size );
    pbump( size );   // Puts the epilog in the put area
    filebuf::sync(); // Sends the epilog to the output file
}
int hstreambuf::sync()
{
    long count = out_waiting();
   if ( count ) {
      convert( count );
   }
   return filebuf::sync();
}

int hstreambuf::overflow( int ch )
{
    long count = out_waiting();
   if ( count ) {
      convert( count );
   }
   return filebuf::overflow( ch );
}
// The following code is specific to the HP LaserJet printer

// Converts a buffer to HP, then writes it
void hstreambuf::convert( long cnt )
{
    char *bufs, *bufd; // Source, destination pointers
    int j = 0;

    bufs = pbase();
    bufd = buffer;
    if( page == 0 ) {
        newline( bufd, j );
    }
    for( int i = 0; i < cnt; i++ ) {
        char c = *( bufs++ );  // Gets character from source buffer
        if( c >= ' ' ) {       // Character is printable
            * ( bufd++ ) = c;
            j++;
            column++;
        }

else if( c == NL ) {            // Moves down one line
            *( bufd++ ) = c;    // Passes character through
            j++;
            line++;
            newline( bufd, j ); // Checks for page break, etc.
        }
        else if( c == FF ) {    // Ejects paper on formfeed
            line = line - line % LPP + LPP;
            newline( bufd, j ); // Checks for page break, etc.
        }
        else if( c == TAB ) {   // Expands tabs
            do {
                *( bufd++ ) = ' ';
                j++;
                column++;
            } while ( column % TABW );
        }
        else if( c == UND ) { // Responds to und manipulator
            pstring( uon, bufd, j );
        }
        else if( c == REG ) { // Responds to reg manipulator
            pstring( uoff, bufd, j );
        }
    }
    setp( buffer, buffer + 1024 ); // Sets new put area
    pbump( j ); // Tells number of characters in the dest buffer
}

// simple manipulators - apply to all ostream classes
ostream& und( ostream& os ) // Turns on underscore mode
{
    os << (char) UND; return os;
}

ostream& reg( ostream& os ) // Turns off underscore mode
{
    os << (char) REG; return os;
}

void hstreambuf::newline( char*& pd, int& jj ) {
// Called for each newline character
   column = 0;
   if ( ( line % ( LPP*2 ) ) == 0 ) { // Even page
      page++;
      pstring( "\033&a+0L", pd, jj );  // Set left margin to zero
      heading( pd, jj );                // Print heading
      pstring( "\033*p0x77Y", pd, jj );// Cursor to (0,77) dots
   }
   if ( ( ( line % LPP ) == 0 ) && ( line % ( LPP*2 ) ) != 0 ) {
   //  Odd page; prepare to move to right column
      page++;
      pstring( "\033*p0x77Y", pd, jj ); // Cursor to (0,77) dots
      pstring( "\033&a+88L", pd, jj );  // Left margin to col 88
   }
}

void hstreambuf::heading( char*& pd, int& jj ) // Prints heading
{
   char hdg[20];
   int i;

   if( page > 1 ) {
      *( pd++ ) = FF;
      jj++;
   }
   pstring( "\033*p0x0Y", pd, jj ); // Top of page
   pstring( uon, pd, jj );          // Underline on
   sprintf( hdg, "Page %-3d", page );
   pstring( hdg, pd, jj );
   for( i=0; i < 80; i++ ) {        // Pads with blanks
      *( pd++ ) = ' ';
      jj++;
   }
   sprintf( hdg, "Page %-3d", page+1 ) ;
   pstring( hdg, pd, jj );
   for( i=0; i < 80; i++ ) {        // Pads with blanks
      *( pd++ ) = ' ';
      jj++;
   }
   pstring( uoff, pd, jj ); // Underline off
}
// Outputs a string to the buffer
void hstreambuf::pstring( char* ph, char*& pd, int& jj )
{
    int len = strlen( ph );
    strncpy( pd, ph, len );
    pd += len;
    jj += len;
}

EXIOS204.CPP reads text lines from the cin object and writes them to the modified cout object.

// exios204.cpp
// hstream Driver program copies cin to cout until end of file
#include "hstream.h"

hstreambuf hsb( 4 ); // 4=stdprn

void main()
{
    char line[200];
    cout = &hsb; // Associates the HP LaserJet streambuf to cout
    while( 1 ) {
       cin.getline( line, 200 );
       if( !cin.good() ) break;
       cout << line << endl;
    }
}

Here are the main points in the preceding code:

  • The new class hstreambuf is derived from filebuf, which is the buffer class for disk file I/O. The filebuf class writes to disk in response to commands from its associated ostream class. The hstreambuf constructor takes an argument that corresponds to the operating system file number, in this case 1, for stdout. This constructor is invoked by this line:
    hstreambuf hsb( 1 );
  • The ostream_withassign assignment operator associates the hstreambuf object with the cout object:
    ostream& operator =( streambuf* sbp );

    This statement in EXIOS204.CPP executes the assignment:

    cout = &hsb;
  • The hstreambuf constructor prints the prolog that sets up the laser printer, then allocates a temporary print buffer.

  • The destructor outputs the epilog text and frees the print buffer when the object goes out of scope, which happens after the exit from main.

  • The streambuf virtual overflow and sync functions do the low-level output. The hstreambuf class overrides these functions to gain control of the byte stream. The functions call the private convert member function.

  • The convert function processes the characters in the hstreambuf buffer and stores them in the object’s temporary buffer. The filebuf functions process the temporary buffer.

  • The details of convert relate more to the PCL language than to the iostream library. Private data members keep track of column, line, and page numbers.

  • The und and reg manipulators control the underscore print attribute by inserting codes 0x02 and 0x03 into the stream. The convert function later translates these codes into printer-specific sequences.

  • The program can be extended easily to embellish the heading, add more formatting features, and so forth.

  • In a more general program, the hstreambuf class could be derived from the streambuf class rather than the filebuf class. The filebuf derivation shown gets the most leverage from existing iostream library code, but it makes assumptions about the implementation of filebuf, particularly the overflow and sync functions. Thus you cannot necessarily expect this example to work with other derived streambuf classes or with filebuf classes provided by other software publishers.


Alphabetic Microsoft iostream Class Library Reference

iostream Class Hierarchy Diagram:


iostream Class List

Abstract Stream Base Class

ios Stream base class.

Input Stream Classes

istream | General-purpose input stream class and base class for other input streams.
ifstream | Input file stream class.
istream_withassign | Input stream class for cin.
istrstream | Input string stream class.

Output Stream Classes

ostream | General-purpose output stream class and base class for other output streams.
ofstream | Output file stream class.
ostream_withassign | Output stream class for cout, cerr, and clog.
ostrstream | Output string stream class.

Input/Output Stream Classes

iostream | General-purpose input/output stream class and base class for other input/output streams.
fstream | Input/output file stream class.
strstream | Input/output string stream class.
stdiostream | Input/output class for standard I/O files.

Stream Buffer Classes

streambuf | Abstract stream buffer base class.
filebuf | Stream buffer class for disk files.
strstreambuf | Stream buffer class for strings.
stdiobuf | Stream buffer class for standard I/O files.

Predefined Stream Initializer Class

Iostream_init Predefined stream initializer class.


filebuf

#include <fstream.h>

The filebuf class is a derived class of streambuf that is specialized for buffered disk file I/O. The buffering is managed entirely within the Microsoft iostream Class Library. filebuf member functions call the run-time low-level I/O routines (the functions declared in IO.H) such as _sopen, _read, and _write.

The file stream classes, ofstream, ifstream, and fstream, use filebuf member functions to fetch and store characters. Some of these member functions are virtual functions of the streambuf class.

The reserve area, put area, and get area are introduced in the streambuf class description. The put area and the get area are always the same for filebuf objects. Also, the get pointer and put pointers are tied; when one moves, so does the other.

Construction/Destruction — Public Members

filebuf

Constructs a filebuf object.

~filebuf

Destroys a filebuf object.

Operations — Public Members

open

Opens a file and attaches it to the filebuf object.

close

Flushes any waiting output and closes the attached file.

setmode

Sets the file’s mode to binary or text.

attach

Attaches the filebuf object to an open file.

Status/Information — Public Members

fd

Returns the stream’s file descriptor.

is_open

Tests whether the file is open.

Stream Buffer Classes

See Also ifstream, ofstream, streambuf, strstreambuf, stdiobuf


filebuf::attach

filebuf* attach( filedesc fd );

Attaches this filebuf object to the open file specified by fd.

Return Value

The function returns NULL when the stream is already attached to a file; otherwise it returns the address of the filebuf object.

Parameter

fd

A file descriptor as returned by a call to the run-time function _open or _sopen. filedesc is a typedef equivalent to int.


filebuf::close

filebuf* close();

Flushes any waiting output, closes the file, and disconnects the file from the filebuf object.

Return Value

If an error occurs, the function returns NULL and leaves the filebuf object in a closed state. If there is no error, the function returns the address of the filebuf object and clears its error state.

filebuf Overview | Stream Buffer Classes

See Also filebuf::open


filebuf::fd

filedesc fd() const;

Returns the file descriptor associated with the filebuf object; filedesc is a typedef equivalent to int.

Return Value

The value is supplied by the underlying file system. The function returns EOF if the object is not attached to a file.

filebuf Overview | Stream Buffer Classes

See Also filebuf::attach


filebuf::filebuf

filebuf();

filebuf( filedesc fd );

filebuf( filedesc fd, char* pr, int nLength );

Parameters

fd

A file descriptor as returned by a call to the run-time function _sopen. filedesc is a typedef equivalent to int.

pr

Pointer to a previously allocated reserve area of length nLength.

nLength

The length (in bytes) of the reserve area.

Remarks

The three filebuf constructors are described as follows:

filebuf()

Constructs a filebuf object without attaching it to a file.

filebuf( filedesc )

Constructs a filebuf object and attaches it to an open file.

filebuf( filedesc, char*, int )

Constructs a filebuf object, attaches it to an open file, and initializes it to use a specified reserve area.


filebuf::~filebuf

~filebuf();

Remarks

Closes the attached file only if that file was opened by the open member function.


filebuf::is_open

int is_open() const;

Return Value

Returns a nonzero value if this filebuf object is attached to an open disk file identified by a file descriptor; otherwise 0.

filebuf Overview | Stream Buffer Classes

See Also filebuf::open


filebuf::open

filebuf* open( const char* szName, int nMode, int nProt = filebuf::openprot );

Opens a disk file and attaches it with this filebuf object.

Return Value

If the file is already open, or if there is an error while opening the file, the function returns NULL; otherwise it returns the filebuf address.

Parameters

szName

The name of the file to be opened during construction.

nMode

An integer containing mode bits defined as ios enumerators that can be combined with the OR ( | ) operator. See the ofstream constructor for a list of the enumerators.

nProt

The file protection specification; defaults to the static integer filebuf::openprot, which is equivalent to the operating system default (filebuf::sh_compat for MS-DOS). The possible values of nProt are:

  • filebuf::sh_compat Compatibility share mode (MS-DOS only).

  • filebuf::sh_none Exclusive mode — no sharing.

  • filebuf::sh_read Read sharing allowed.

  • filebuf::sh_write Write sharing allowed.

    You can combine the filebuf::sh_read and filebuf::sh_write modes with the logical OR ( || ) operator.

filebuf Overview | Stream Buffer Classes

See Also filebuf::is_open, filebuf::close, filebuf::~filebuf


filebuf::setmode

int setmode( int nMode = filebuf::text );

Parameter

nMode

An integer that must be one of the static filebuf constants. The nMode parameter must have one of the following values:

  • filebuf::text Text mode (newline characters translated to and from carriage return–linefeed pairs under MS-DOS).

  • filebuf::binary Binary mode (no translation).

Return Value

The previous mode if there is no error; otherwise 0.

Remarks

Sets the binary/text mode of the stream’s filebuf object.

filebuf Overview | Stream Buffer Classes

See Also ios binary manipulator, ios text manipulator


fstream

#include <fstream.h>

The fstream class is an iostream derivative specialized for combined disk file input and output. Its constructors automatically create and attach a filebuf buffer object.

See filebuf class for information on the get and put areas and their associated pointers. Although the filebuf object’s get and put pointers are theoretically independent, the get area and the put area are not active at the same time. When the stream’s mode changes from input to output, the get area is emptied and the put area is reinitialized. When the mode changes from output to input, the put area is flushed and the get area is reinitialized. Thus, either the get pointer or the put pointer is null at all times.

Construction/Destruction — Public Members

fstream

Constructs an fstream object.

~fstream

Destroys an fstream object.

Operations — Public Members

open

Opens a file and attaches it to the filebuf object and thus to the stream.

close

Flushes any waiting output and closes the stream’s file.

setbuf

Attaches the specified reserve area to the stream’s filebuf object.

setmode

Sets the stream’s mode to binary or text.

attach

Attaches the stream (through the filebuf object) to an open file.

Status/Information — Public Members

rdbuf

Gets the stream’s filebuf object.

fd

Returns the file descriptor associated with the stream.

is_open

Tests whether the stream’s file is open.

Input Stream Classes

See Also ifstream, ofstream, strstream, stdiostream, filebuf


fstream::attach

void attach( filedesc fd );

Attaches this stream to the open file specified by fd.

Parameter

fd

A file descriptor as returned by a call to the run-time function _open or _sopen; filedesc is a typedef equivalent to int.

Remarks

The function fails when the stream is already attached to a file. In that case, the function sets ios::failbit in the stream’s error state.

fstream Overview | Input Stream Classes

See Also filebuf::attach, fstream::fd


fstream::close

void close();

Remarks

Calls the close member function for the associated filebuf object. This function, in turn, flushes any waiting output, closes the file, and disconnects the file from the filebuf object. The filebuf object is not destroyed.

The stream’s error state is cleared unless the call to filebuf::close fails.

fstream Overview | Input Stream Classes

See Also filebuf::close, fstream::open, fstream::is_open


fstream::fd

filedesc fd() const;

Remarks

Returns the file descriptor associated with the stream. filedesc is a typedef equivalent to int. Its value is supplied by the underlying file system.

fstream Overview | Input Stream Classes

See Also filebuf::fd, fstream::attach


fstream::fstream

fstream();

fstream( const char* szName, int nMode, int nProt = filebuf::openprot );

fstream( filedesc fd );

fstream( filedesc fd, char* pch, int nLength );

Parameters

szName

The name of the file to be opened during construction.

nMode

An integer that contains mode bits defined as ios enumerators that can be combined with the bitwise OR ( | ) operator. The nMode parameter must have one of the following values:

  • ios::app The function performs a seek to the end of file. When new bytes are written to the file, they are always appended to the end, even if the position is moved with the ostream::seekp function.

  • ios::ate The function performs a seek to the end of file. When the first new byte is written to the file, it is appended to the end, but when subsequent bytes are written, they are written to the current position.

  • ios::in The file is opened for input. The original file (if it exists) will not be truncated.

  • ios::out The file is opened for output.

  • ios::trunc If the file already exists, its contents are discarded. This mode is implied if ios::out is specified, and ios::ate, ios::app, and ios:in are not specified.

  • ios::nocreate If the file does not already exist, the function fails.

  • ios::noreplace If the file already exists, the function fails.

  • ios::binary Opens the file in binary mode (the default is text mode).

    Note that there is no ios::in or ios::out default mode for fstream objects. You must specify both modes if your fstream object must both read and write files.

nProt

The file protection specification; defaults to the static integer filebuf::openprot, which is equivalent to the operating system default, filebuf::sh_compat, under MS-DOS. The possible nProt values are as follows:

  • filebuf::sh_compat Compatibility share mode (MS-DOS only).

  • filebuf::sh_none Exclusive mode — no sharing.

  • filebuf::sh_read Read sharing allowed.

  • filebuf::sh_write Write sharing allowed.

    The filebuf::sh_read and filebuf::sh_write modes can be combined with the logical OR ( || ) operator.

fd

A file descriptor as returned by a call to the run-time function _open or _sopen. filedesc is a typedef equivalent to int.

pch

Pointer to a previously allocated reserve area of length nLength. A NULL value (or nLength = 0) indicates that the stream will be unbuffered.

nLength

The length (in bytes) of the reserve area (0 = unbuffered).

Remarks

The four fstream constructors are:

  • fstream() Constructs an fstream object without opening a file.

  • fstream( const char*, int, int ) Contructs an fstream object, opening the specified file.

  • fstream( filedesc ) Constructs an fstream object that is attached to an open file.

  • fstream( filedesc, char*, int ) Constructs an fstream object that is associated with a filebuf object. The filebuf object is attached to an open file and to a specified reserve area.

All fstream constructors construct a filebuf object. The first three use an internally allocated reserve area, but the fourth uses a user-allocated area. The user-allocated area is not automatically released during destruction.


fstream::~fstream

~fstream();

Remarks

Flushes the buffer, then destroys an fstream object, along with its associated filebuf object. The file is closed only if it was opened by the constructor or by the open member function.

The filebuf destructor releases the reserve buffer only if it was internally allocated.


fstream::is_open

int is_open() const;

Return Value

Returns a nonzero value if this stream is attached to an open disk file identified by a file descriptor; otherwise 0.

fstream Overview | Input Stream Classes

See Also filebuf::is_open, fstream::open, fstream::close


fstream::open

void open( const char* szName, int nMode, int nProt = filebuf::openprot );

Opens a disk file and attaches it to the stream’s filebuf object.

Parameters

szName

The name of the file to be opened during construction.

nMode

An integer containing mode bits defined as ios enumerators that can be combined with the OR ( | ) operator. See the fstream constructor for a list of the enumerators. There is no default; a valid mode must be specified.

nProt

The file protection specification; defaults to the static integer filebuf::openprot. See the fstream constructor for a list of the other allowed values.

Remarks

If the filebuf object is already attached to an open file, or if a filebuf call fails, the ios::failbit is set. If the file is not found, then the ios::failbit is set only if the ios::nocreate mode was used.

fstream Overview | Input Stream Classes

See Also filebuf::open, fstream::fstream, fstream::close, fstream::is_open


fstream::rdbuf

filebuf* rdbuf() const;

Remarks

Returns a pointer to the filebuf buffer object that is associated with this stream. (This is not the character buffer; the filebuf object contains a pointer to the character area.)


fstream::setbuf

streambuf* setbuf( char* pch, int nLength );

Attaches the specified reserve area to the stream’s filebuf object.

Return Value

If the file is open and a buffer has already been allocated, the function returns NULL; otherwise it returns a pointer to the filebuf cast as a streambuf. The reserve area will not be released by the destructor.

Parameters

pch

A pointer to a previously allocated reserve area of length nLength. A NULL value indicates an unbuffered stream.

nLength

The length (in bytes) of the reserve area. A length of 0 indicates an unbuffered stream.


fstream::setmode

int setmode( int nMode = filebuf::text );

Sets the binary/text mode of the stream’s filebuf object. It can be called only after the file is opened.

Return Value

The previous mode; –1 if the parameter is invalid, the file is not open, or the mode cannot be changed.

Parameter

nMode

An integer that must be one of the following static filebuf constants:

  • filebuf::text Text mode (newline characters translated to and from carriage-return – linefeed pairs).

  • filebuf::binary Binary mode (no translation).

fstream Overview | Input Stream Classes

See Also ios binary manipulator, ios text manipulator


ifstream

#include <fstream.h>

The ifstream class is an istream derivative specialized for disk file input. Its constructors automatically create and attach a filebuf buffer object.

The filebuf class documentation describes the get and put areas and their associated pointers. Only the get area and the get pointer are active for the ifstream class.

Construction/Destruction — Public Members

ifstream

Constructs an ifstream object.

~ifstream

Destroys an ifstream object.

Operations — Public Members

open

Opens a file and attaches it to the filebuf object and thus to the stream.

close

Closes the stream’s file.

setbuf

Associates the specified reserve area to the stream’s filebuf object.

setmode

Sets the stream’s mode to binary or text.

attach

Attaches the stream (through the filebuf object) to an open file.

Status/Information — Public Members

rdbuf

Gets the stream’s filebuf object.

fd

Returns the file descriptor associated with the stream.

is_open

Tests whether the stream’s file is open.

Input Stream Classes

See Also filebuf, streambuf, ofstream, fstream


ifstream::attach

void attach( filedesc fd );

Attaches this stream to the open file specified by fd.

Parameter

fd

A file descriptor as returned by a call to the run-time function _open or _sopen; filedesc is a typedef equivalent to int.

Remarks

The function fails when the stream is already attached to a file. In that case, the function sets ios::failbit in the stream’s error state.

ifstream Overview | Input Stream Classes

See Also filebuf::attach, ifstream::fd


ifstream::close

void close();

Remarks

Calls the close member function for the associated filebuf object. This function, in turn, closes the file and disconnects the file from the filebuf object. The filebuf object is not destroyed.

The stream’s error state is cleared unless the call to filebuf::close fails.

ifstream Overview | Input Stream Classes

See Also filebuf::close, ifstream::open, ifstream::is_open


ifstream::fd

filedesc fd() const;

Return Value

Returns the file descriptor associated with the stream; filedesc is a typedef equivalent to int. Its value is supplied by the underlying file system.

ifstream Overview | Input Stream Classes

See Also filebuf::fd, ifstream::attach


ifstream::ifstream

ifstream();

ifstream( const char* szName, int nMode = ios::in, int nProt = filebuf::openprot );

ifstream( filedesc fd );

ifstream( filedesc fd, char* pch, int nLength );

Parameters

szName

The name of the file to be opened during construction.

nMode

An integer that contains mode bits defined as ios enumerators that can be combined with the bitwise OR ( | ) operator. The nMode parameter must have one of the following values:

  • ios::in The file is opened for input (default).

  • ios::nocreate If the file does not already exist, the function fails.

  • ios::binary Opens the file in binary mode (the default is text mode).

    Note that the ios::nocreate flag is necessary if you intend to test for the file’s existence (the usual case).

nProt

The file protection specification; defaults to the static integer filebuf::openprot that is equivalent to filebuf::sh_compat. The possible nProt values are:

  • filebuf::sh_compat Compatibility share mode.

  • filebuf::sh_none Exclusive mode — no sharing.

  • filebuf::sh_read Read sharing allowed.

  • filebuf::sh_write Write sharing allowed.

    To combine the filebuf::sh_read and filebuf::sh_write modes, use the logical OR ( || ) operator.

fd

A file descriptor as returned by a call to the run-time function _open or _sopen; filedesc is a typedef equivalent to int.

pch

Pointer to a previously allocated reserve area of length nLength. A NULL value (or nLength = 0) indicates that the stream will be unbuffered.

nLength

The length (in bytes) of the reserve area (0 = unbuffered).

Remarks

The four ifstream constructors are:

  • ifstream() Constructs an ifstream object without opening a file.

  • ifstream( const char*, int, int ) Contructs an ifstream object, opening the specified file.

  • ifstream( filedesc ) Constructs an ifstream object that is attached to an open file.

  • ifstream( filedesc, char*, int ) Constructs an ifstream object that is associated with a filebuf object. The filebuf object is attached to an open file and to a specified reserve area.

All ifstream constructors construct a filebuf object. The first three use an internally allocated reserve area, but the fourth uses a user-allocated area.


ifstream::~ifstream

~ifstream();

Remarks

Destroys an ifstream object along with its associated filebuf object. The file is closed only if it was opened by the constructor or by the open member function.

The filebuf destructor releases the reserve buffer only if it was internally allocated.


ifstream::is_open

int is_open() const;

Return Value

Returns a nonzero value if this stream is attached to an open disk file identified by a file descriptor; otherwise 0.

ifstream Overview | Input Stream Classes

See Also filebuf::is_open, ifstream::open, ifstream::close


ifstream::open

void open( const char* szName, int nMode = ios::in, int nProt = filebuf::openprot );

Parameters

szName

The name of the file to be opened during construction.

nMode

An integer containing bits defined as ios enumerators that can be combined with the OR ( | ) operator. See the ifstream constructor for a list of the enumerators. The ios::in mode is implied.

nProt

The file protection specification; defaults to the static integer filebuf::openprot. See the ifstream constructor for a list of the other allowed values.

Remarks

Opens a disk file and attaches it to the stream’s filebuf object. If the filebuf object is already attached to an open file, or if a filebuf call fails, the ios::failbit is set. If the file is not found, then the ios::failbit is set only if the ios::nocreate mode was used.

ifstream Overview | Input Stream Classes

See Also filebuf::open, ifstream::ifstream, ifstream::close, ifstream::is_open, ios::flags


ifstream::rdbuf

filebuf* rdbuf() const;

Return Value

Returns a pointer to the filebuf buffer object that is associated with this stream. (This is not the character buffer; the filebuf object contains a pointer to the character area.)


ifstream::setbuf

streambuf* setbuf( char* pch, int nLength );

Attaches the specified reserve area to the stream’s filebuf object.

Return Value

If the file is open and a buffer has already been allocated, the function returns NULL; otherwise it returns a pointer to the filebuf, which is cast as a streambuf. The reserve area will not be released by the destructor.

Parameters

pch

A pointer to a previously allocated reserve area of length nLength. A NULL value indicates an unbuffered stream.

nLength

The length (in bytes) of the reserve area. A length of 0 indicates an unbuffered stream.


ifstream::setmode

int setmode( int nMode = filebuf::text );

Return Value

The previous mode; –1 if the parameter is invalid, the file is not open, or the mode cannot be changed.

Parameters

nMode

An integer that must be one of the following static filebuf constants:

  • filebuf::text Text mode (newline characters translated to and from carriage return–linefeed pairs).

  • filebuf::binary Binary mode (no translation).

Remarks

This function sets the binary/text mode of the stream’s filebuf object. It may be called only after the file is opened.

ifstream Overview | Input Stream Classes

See Also ios binary manipulator, ios text manipulator


ios

#include <iostream.h>

As the iostream class hierarchy diagram shows, ios is the base class for all the input/output stream classes. While ios is not technically an abstract base class, you will not usually construct ios objects, nor will you derive classes directly from ios. Instead, you will use the derived classes istream and ostream or other derived classes.

Even though you will not use ios directly, you will be using many of the inherited member functions and data members described here. Remember that these inherited member function descriptions are not duplicated for derived classes.

Data Members (static) — Public Members

basefield

Mask for obtaining the conversion base flags (dec, oct, or hex).

adjustfield

Mask for obtaining the field padding flags (left, right, or internal).

floatfield

Mask for obtaining the numeric format (scientific or fixed).

Construction/Destruction — Public Members

ios

Constructor for use in derived classes.

~ios

Virtual destructor.

Flag and Format Access Functions — Public Members

flags

Sets or reads the stream’s format flags.

setf

Manipulates the stream’s format flags.

unsetf

Clears the stream’s format flags.

fill

Sets or reads the stream’s fill character.

precision

Sets or reads the stream’s floating-point format display precision.

width

Sets or reads the stream’s output field width.

Status-Testing Functions — Public Members

good

Indicates good stream status.

bad

Indicates a serious I/O error.

eof

Indicates end of file.

fail

Indicates a serious I/O error or a possibly recoverable I/O formatting error.

rdstate

Returns the stream’s error flags.

clear

Sets or clears the stream’s error flags.

User-Defined Format Flags — Public Members

bitalloc

Provides a mask for an unused format bit in the stream’s private flags variable (static function).

xalloc

Provides an index to an unused word in an array reserved for special-purpose stream state variables (static function).

iword

Converts the index provided by xalloc to a reference (valid only until the next xalloc).

pword

Converts the index provided by xalloc to a pointer (valid only until the next xalloc).

Other Functions — Public Members

delbuf

Controls the connection of streambuf deletion with ios destruction.

rdbuf

Gets the stream’s streambuf object.

sync_with_stdio

Synchronizes the predefined objects cin, cout, cerr, and clog with the standard I/O system.

tie

Ties a specified ostream to this stream.

Operators — Public Members

operator void*

Converts a stream to a pointer that can be used only for error checking.

operator !

Returns a nonzero value if a stream I/O error occurs.

ios Manipulators

dec

Causes the interpretation of subsequent fields in decimal format (the default mode).

hex

Causes the interpretation of subsequent fields in hexadecimal format.

oct

Causes the interpretation of subsequent fields in octal format.

binary

Sets the stream’s mode to binary (stream must have an associated filebuf buffer).

text

Sets the stream’s mode to text, the default mode (stream must have an associated filebuf buffer).

Parameterized Manipulators

(#include <iomanip.h> required)

setiosflags

Sets the stream’s format flags.

resetiosflags

Resets the stream’s format flags.

setfill

Sets the stream’s fill character.

setprecision

Sets the stream’s floating-point display precision.

setw

Sets the stream’s field width (for the next field only).

Abstract Stream Base Class

See Also istream, ostream


ios::bad

int bad() const;

Return Value

Returns a nonzero value to indicate a serious I/O error. This is the same as setting the badbit error state. Do not continue I/O operations on the stream in this situation.

ios Overview | Abstract Stream Base Class

See Also ios::good, ios::fail, ios::rdstate


ios::bitalloc

static long bitalloc();

Remarks

Provides a mask for an unused format bit in the stream’s private flags variable (static function). The ios class currently defines 15 format flag bits accessible through flags and other member functions. These bits reside in a 32-bit private ios data member and are accessed through enumerators such as ios::left and ios::hex.

The bitalloc member function provides a mask for a previously unused bit in the data member. Once you obtain the mask, you can use it to set or test the corresponding custom flag bit in conjunction with the ios member functions and manipulators listed under “See Also.”

ios Overview | Abstract Stream Base Class

See Also ios::flags, ios::setf, ios::unsetf, ios setiosflags manipulator, ios resetiosflags manipulator


ios::clear

void clear( int nState = 0 );

Parameter

nState

If 0, all error bits are cleared; otherwise bits are set according to the following masks (ios enumerators) that can be combined using the bitwise OR ( | ) operator. The nState parameter must have one of the following values:

  • ios::goodbit No error condition (no bits set).

  • ios::eofbit End of file reached.

  • ios::failbit A possibly recoverable formatting or conversion error.

  • ios::badbit A severe I/O error.

Remarks

Sets or clears the error-state flags. The rdstate function can be used to read the current error state.

ios Overview | Abstract Stream Base Class

See Also ios::rdstate, ios::good, ios::bad, ios::eof


ios::delbuf

void delbuf( int nDelFlag );

int delbuf() const;

Parameter

nDelFlag

A nonzero value indicates that ~ios should delete the stream’s attached streambuf object. A 0 value prevents deletion.

Remarks

The first overloaded delbuf function assigns a value to the stream’s buffer-deletion flag. The second function returns the current value of the flag.

This function is public only because it is accessed by the Iostream_init class. Treat it as protected.

ios Overview | Abstract Stream Base Class

See Also ios::rdbuf, ios::~ios


ios::eof

int eof() const;

Return Value

Returns a nonzero value if end of file has been reached. This is the same as setting the eofbit error flag.


ios::fail

int fail() const;

Return Value

Returns a nonzero value if any I/O error (not end of file) has occurred. This condition corresponds to either the badbit or failbit error flag being set. If a call to bad returns 0, you can assume that the error condition is nonfatal and that you can probably continue processing after you clear the flags.

ios Overview | Abstract Stream Base Class

See Also ios::bad, ios::clear


ios::fill

char fill( char cFill );

char fill() const;

Return Value

The first overloaded function sets the stream’s internal fill character variable to cFill and returns the previous value. The default fill character is a space.

The second fill function returns the stream’s fill character.

Parameter

cFill

The new fill character to be used as padding between fields.

ios Overview | Abstract Stream Base Class

See Also ios setfill manipulator


ios::flags

long flags( long lFlags );

long flags() const;

Return Value

The first overloaded flags function sets the stream’s internal flags variable to lFlags and returns the previous value.

The second function returns the stream’s current flags.

Parameter

lFlags

The new format flag values for the stream. The values are specified by the following bit masks (ios enumerators) that can be combined using the bitwise OR ( | ) operator. The lFlags parameter must have one of the following values:

  • ios::skipws Skip white space on input.

  • ios::left Left-align values; pad on the right with the fill character.

  • ios::right Right-align values; pad on the left with the fill character (default alignment).

  • ios::internal Add fill characters after any leading sign or base indication, but before the value.

  • ios::dec Format numeric values as base 10 (decimal) (default radix).

  • ios::oct Format numeric values as base 8 (octal).

  • ios::hex Format numeric values as base 16 (hexadecimal).

  • ios::showbase Display numeric constants in a format that can be read by the C++ compiler.

  • ios::showpoint Show decimal point and trailing zeros for floating-point values.

  • ios::uppercase Display uppercase A through F for hexadecimal values and E for scientific values.

  • ios::showpos Show plus signs (+) for positive values.

  • ios::scientific Display floating-point numbers in scientific format.

  • ios::fixed Display floating-point numbers in fixed format.

  • ios::unitbuf Cause ostream::osfx to flush the stream after each insertion. By default, cerr is unit buffered.

  • ios::stdio Cause ostream::osfx to flush stdout and stderr after each insertion.

ios Overview | Abstract Stream Base Class

See Also ios::setf, ios::unsetf, ios setiosflags manipulator, ios resetiosflags manipulator, ios::adjustfield, ios::basefield, ios::floatfield


ios::good

int good() const;

Return Value

Returns a nonzero value if all error bits are clear. Note that the good member function is not simply the inverse of the bad function.

ios Overview | Abstract Stream Base Class

See Also ios::bad, ios::fail, ios::rdstate


ios::init

Protected —>

void init( streambuf* psb );

END Protected

Parameter

psb

A pointer to an existing streambuf object.

Remarks

Associates an object of a streambuf-derived class with this stream and, if necessary, deletes a dynamically created stream buffer object that was previously associated. The init function is useful in derived classes in conjunction with the protected default istream, ostream, and iostream constructors. Thus, an ios-derived class constructor can construct and attach its own predetermined stream buffer object.

ios Overview | Abstract Stream Base Class

See Also istream::istream, ostream::ostream, iostream::iostream


ios::ios

ios( streambuf* psb );

Parameter

psb

A pointer to an existing streambuf object.

Remarks

Constructor for ios. You will seldom need to invoke this constructor except in derived classes. Generally, you will be deriving classes not from ios but from istream, ostream, and iostream.


ios::~ios

virtual ~ios();

Remarks

Virtual destructor for ios.


ios::iword

long& iword( int nIndex ) const;

Parameters

nIndex

An index to a table of words that are associated with the ios object.

Remarks

The xalloc member function provides the index to the table of special-purpose words. The pword function converts that index to a reference to a 32-bit word.

ios Overview | Abstract Stream Base Class

See Also ios::xalloc, ios::pword


ios::precision

int precision( int np );

int precision() const;

Return Value

The first overloaded precision function sets the stream’s internal floating-point precision variable to np and returns the previous value. The default precision is six digits. If the display format is scientific or fixed, the precision indicates the number of digits after the decimal point. If the format is automatic (neither floating point nor fixed), the precision indicates the total number of significant digits.

The second function returns the stream’s current precision value.

Parameter

np

An integer that indicates the number of significant digits or significant decimal digits to be used for floating-point display.

ios Overview | Abstract Stream Base Class

See Also ios setprecision manipulator


ios::pword

void*& pword( int nIndex ) const;

Parameter

nIndex

An index to a table of words that are associated with the ios object.

Remarks

The xalloc member function provides the index to the table of special-purpose words. The pword function converts that index to a reference to a pointer to a 32-bit word.

ios Overview | Abstract Stream Base Class

See Also ios::xalloc, ios::iword


ios::rdbuf

streambuf* rdbuf() const;

Return Value

Returns a pointer to the streambuf object that is associated with this stream. The rdbuf function is useful when you need to call streambuf member functions.


ios::rdstate

int rdstate() const;

Return Value

Returns the current error state as specified by the following masks (ios enumerators):

  • ios::goodbit No error condition.

  • ios::eofbit End of file reached.

  • ios::failbit A possibly recoverable formatting or conversion error.

  • ios::badbit A severe I/O error or unknown state.

The returned value can be tested against a mask with the AND (&) operator.

ios Overview | Abstract Stream Base Class

See Also ios::clear


ios::setf

long setf( long lFlags );

long setf( long lFlags, long lMask );

Return Value

The first overloaded setf function turns on only those format bits that are specified by 1s in lFlags. It returns a long that contains the previous value of all the flags.

The second function alters those format bits specified by 1s in lMask. The new values of those format bits are determined by the corresponding bits in lFlags. It returns a long that contains the previous value of all the flags.

Parameters

lFlags

Format flag bit values. See the flags member function for a list of format flags. To combine these flags, use the bitwise OR ( | ) operator.

lMask

Format flag bit mask.

ios Overview | Abstract Stream Base Class

See Also ios::flags, ios::unsetf, ios setiosflags manipulator


ios::sync_with_stdio

static void sync_with_stdio();

Remarks

Synchronizes the C++ streams with the standard I/O system. The first time this function is called, it resets the predefined streams (cin, cout, cerr, clog) to use a stdiobuf object rather than a filebuf object. After that, you can mix I/O using these streams with I/O using stdin, stdout, and stderr. Expect some performance decrease because there is buffering both in the stream class and in the standard I/O file system.

After the call to sync_with_stdio, the ios::stdio bit is set for all affected predefined stream objects, and cout is set to unit buffered mode.


ios::tie

ostream* tie( ostream* pos );

ostream* tie() const;

Return Value

The first overloaded tie function ties this stream to the specified ostream and returns the value of the previous tie pointer or NULL if this stream was not previously tied. A stream tie enables automatic flushing of the ostream when more characters are needed, or there are characters to be consumed.

By default, cin is initially tied to cout so that attempts to get more characters from standard input may result in flushing standard output. In addition, cerr and clog are tied to cout by default.

The second function returns the value of the previous tie pointer or NULL if this stream was not previously tied.

Parameter

pos

A pointer to an ostream object.


ios::unsetf

long unsetf( long lFlags );

Return Value

Clears the format flags specified by 1s in lFlags. It returns a long that contains the previous value of all the flags.

Parameter

lFlags

Format flag bit values. See the flags member function for a list of format flags.

ios Overview | Abstract Stream Base Class

See Also ios::flags, ios::setf, ios resetiosflags manipulator


ios::width

int width( int nw );

int width() const;

Return Value

The first overloaded width function sets the stream’s internal field width variable to nw. When the width is 0 (the default), inserters insert only the number of characters necessary to represent the inserted value. When the width is not 0, the inserters pad the field with the stream’s fill character, up to nw. If the unpadded representation of the field is larger than nw, the field is not truncated. Thus, nw is a minimum field width.

The internal width value is reset to 0 after each insertion or extraction.

The second overloaded width function returns the current value of the stream’s width variable.

Parameter

nw

The minimum field width in characters.

ios Overview | Abstract Stream Base Class

See Also ios setw manipulator


ios::xalloc

static int xalloc();

Return Value

Provides extra ios object state variables without the need for class derivation. It does so by returning an index to an unused 32-bit word in an internal array. This index can subsequently be converted into a reference or pointer by using the iword or pword member functions.

Any call to xalloc invalidates values returned by previous calls to iword and pword.

ios Overview | Abstract Stream Base Class

ios::iword, ios::pword


ios::operator void*

operator void* () const;

An operator that converts a stream to a pointer that can be compared to 0.

Return Value

The conversion returns 0 if either failbit or badbit is set in the stream’s error state. See rdstate for a description of the error state masks. A nonzero pointer is not meant to be dereferenced.

ios Overview | Abstract Stream Base Class

See Also ios::good, ios::fail


ios::operator !

int operator !() const;

Return Value

Returns a nonzero value if either failbit or badbit is set in the stream’s error state. See rdstate for a description of the error state masks.

ios Overview | Abstract Stream Base Class

See Also ios::good, ios::fail


ios::adjustfield

static const long adjustfield;

Remarks

A mask for obtaining the padding flag bits (left, right, or internal).

Example

extern ostream os;
if( ( os.flags() & ios::adjustfield ) == ios::left ) .....

ios Overview | Abstract Stream Base Class

See Also ios::flags


ios::basefield

static const long basefield;

Remarks

A mask for obtaining the current radix flag bits (dec, oct, or hex).

Example

extern ostream os;
if( ( os.flags() & ios::basefield ) == ios::hex ) .....

ios Overview | Abstract Stream Base Class

See Also ios::flags


ios::floatfield

static const long floatfield;

Remarks

A mask for obtaining floating-point format flag bits (scientific or fixed).

Example

extern ostream os;
if( ( os.flags() & ios::floatfield ) == ios::scientific ) .....

ios Overview | Abstract Stream Base Class

See Also ios::flags


Manipulators


ios& binary

binary

Remarks

Sets the stream’s mode to binary. The default mode is text.

The stream must have an associated filebuf buffer.

ios Overview | Abstract Stream Base Class

See Also ios text manipulator, ofstream::setmode, ifstream::setmode, filebuf::setmode


ios& dec

dec

Remarks

Sets the format conversion base to 10 (decimal).

ios Overview | Abstract Stream Base Class

See Also ios hex manipulator, ios oct manipulator


ios& hex

hex

Remarks

Sets the format conversion base to 16 (hexadecimal).

ios Overview | Abstract Stream Base Class

See Also ios dec manipulator, ios oct manipulator


ios& oct

oct

Remarks

Sets the format conversion base to 8 (octal).

ios Overview | Abstract Stream Base Class

See Also ios dec manipulator, ios hex manipulator


resetiosflags

SMANIP( long ) resetiosflags( long lFlags );

#include <iomanip.h>

Parameter

lFlags

Format flag bit values. See the flags member function for a list of format flags. To combine these flags, use the OR ( | ) operator.

Remarks

This parameterized manipulator clears only the specified format flags. This setting remains in effect until you change it.


setfill

SMANIP( int ) setfill( int nFill );

#include <iomanip.h>

Parameter

nFill

The new fill character to be used as padding between fields.

Remarks

This parameterized manipulator sets the stream’s fill character. The default is a space. This setting remains in effect until the next change.


setiosflags

SMANIP( long ) setiosflags( long lFlags );

#include <iomanip.h>

Parameter

lFlags

Format flag bit values. See the flags member function for a list of format flags. To combine these flags, use the OR ( | ) operator.

Remarks

This parameterized manipulator sets only the specified format flags. This setting remains in effect until the next change.


setprecision

SMANIP( int ) setprecision( int np );

#include <iomanip.h>

Parameter

np

An integer that indicates the number of significant digits or significant decimal digits to be used for floating-point display.

Remarks

This parameterized manipulator sets the stream’s internal floating-point precision variable to np. The default precision is six digits. If the display format is scientific or fixed, then the precision indicates the number of digits after the decimal point. If the format is automatic (neither floating point nor fixed), then the precision indicates the total number of significant digits. This setting remains in effect until the next change.


setw

SMANIP( int ) setw( int nw );

#include <iomanip.h>

Parameter

nw

The field width in characters.

Remarks

This parameterized manipulator sets the stream’s internal field width parameter. See the width member function for more information. This setting remains in effect only for the next insertion.


ios& text

text

Sets the stream’s mode to text (the default mode).

Remarks

The stream must have an associated filebuf buffer.

ios Overview | Abstract Stream Base Class

See Also ios binary manipulator, ofstream::setmode, ifstream::setmode, filebuf::setmode


iostream

#include <iostream.h>

The iostream class provides the basic capability for sequential and random-access I/O. It inherits functionality from the istream and ostream classes.

The iostream class works in conjunction with classes derived from streambuf (for example, filebuf). In fact, most of the iostream “personality” comes from its attached streambuf class. You can use iostream objects for sequential disk I/O if you first construct an appropriate filebuf object. More often, you will use objects of classes fstream and strstream.

Derivation

For derivation suggestions, see the istream and ostream classes.

Public Members

iostream

Constructs an iostream object that is attached to an existing streambuf object.

~iostream

Destroys an iostream object.

Protected Members

iostream

Acts as a void-argument iostream constructor.

Input/Output Stream Classes

See Also istream, ostream, fstream, strstream, stdiostream


iostream::iostream

Public

iostream( streambuf* psb );

END Public

Protected

iostream( );

END Protected

Parameter

psb

A pointer to an existing streambuf object (or an object of a derived class).

Remarks

Constructs an object of type iostream.

iostream Overview | Input/Output Stream Classes

See Also ios::init


iostream::~iostream

virtual ~iostream();

Remarks

Virtual destructor for the iostream class.


Iostream_init

#include <iostream.h>

The Iostream_init class is a static class that initializes the predefined stream objects cin, cout, cerr, and clog. A single object of this class is constructed “invisibly” in response to any reference to the predefined objects. The class is documented for completeness only. You will not normally construct objects of this class.

Public Members

Iostream_init

A constructor that initializes cin, cout, cerr, and clog.

~Iostream_init

The destructor for the Iostream_init class.

Predefined Stream Initializer Class


Iostream_init::Iostream_init

Iostream_init();

Remarks

Iostream_init constructor that initializes cin, cout, cerr, and clog. For internal use only.


Iostream_init::~Iostream_init

~Iostream_init();

Remarks

Iostream_init destructor. For internal use only.


istream

#include <iostream.h>

The istream class provides the basic capability for sequential and random-access input. An istream object has a streambuf-derived object attached, and the two classes work together; the istream class does the formatting, and the streambuf class does the low-level buffered input.

You can use istream objects for sequential disk input if you first construct an appropriate filebuf object. More often, you will use the predefined stream object cin (which is actually an object of class istream_withassign), or you will use objects of classes ifstream (disk file streams) and istrstream (string streams).

Derivation

It is not always necessary to derive from istream to add functionality to a stream; consider deriving from streambuf instead, as illustrated in Deriving Your Own Stream Classes. The ifstream and istrstream classes are examples of istream-derived classes that construct member objects of predetermined derived streambuf classes. You can add manipulators without deriving a new class.

If you add new extraction operators for a derived istream class, then the rules of C++ dictate that you must reimplement all the base class extraction operators. See the “Derivation” section of class ostream for an efficient reimplementation technique.

Construction/Destruction — Public Members

istream

Constructs an istream object attached to an existing object of a streambuf-derived class.

~istream

Destroys an istream object.

Prefix/Suffix Functions — Public Members

ipfx

Check for error conditions prior to extraction operations (input prefix function).

isfx

Called after extraction operations (input suffix function).

Input Functions — Public Members

get

Extracts characters from the stream up to, but not including, delimiters.

getline

Extracts characters from the stream (extracts and discards delimiters).

read

Extracts data from the stream.

ignore

Extracts and discards characters.

peek

Returns a character without extracting it from the stream.

gcount

Counts the characters extracted in the last unformatted operation.

eatwhite

Extracts leading white space.

Other Functions — Public Members

putback

Puts characters back to the stream.

sync

Synchronizes the stream buffer with the external source of characters.

seekg

Changes the stream’s get pointer.

tellg

Gets the value of the stream’s get pointer.

Operators — Public Members

operator >>

Extraction operator for various types.

Protected Members

istream

Constructs an istream object.

Manipulators

ws

Extracts leading white space.

Input Stream Classes

See Also streambuf, ifstream, istrstream, istream_withassign


istream::eatwhite

void eatwhite();

Remarks

Extracts white space from the stream by advancing the get pointer past spaces and tabs.

istream Overview | Input Stream Classes

See Also istream ws manipulator


istream::gcount

int gcount() const;

Remarks

Returns the number of characters extracted by the last unformatted input function. Formatted extraction operators may call unformatted input functions and thus reset this number.

istream Overview | Input Stream Classes

See Also istream::get, istream::getline, istream::ignore, istream::read


istream::get

int get();&

istream& get( char* pch, int nCount, char delim = '\n' );

istream& get( unsigned char* puch, int nCount, char delim = '\n' );

istream& get( signed char* psch, int nCount, char delim = '\n' );

istream& get( char& rch );

istream& get( unsigned char& ruch );

istream& get( signed char& rsch );

istream& get( streambuf& rsb, char delim = '\n' );

Parameters

pch, puch, psch

A pointer to a character array.

nCount

The maximum number of characters to store, including the terminating NULL.

delim

The delimiter character (defaults to newline).

rch, ruch, rsch

A reference to a character.

rsb

A reference to an object of a streambuf-derived class.

Remarks

These functions extract data from an input stream as follows:

Variation | Description
get(); | Extracts a single character from the stream and returns it.
get( char*, int, char ); | Extracts characters from the stream until either delim is found, the limit nCount is reached, or the end of file is reached. The characters are stored in the array followed by a null terminator.
get( char& ); | Extracts a single character from the stream and stores it as specified by the reference argument.
get( streambuf&, char ); | Gets characters from the stream and stores them in a streambuf object until the delimiter is found or the end of the file is reached. The ios::failbit flag is set if the streambuf output operation fails.

In all cases, the delimiter is neither extracted from the stream nor returned by the function. The getline function, in contrast, extracts but does not store the delimiter.

istream Overview | Input Stream Classes

See Also istream::getline, istream::read, istream::ignore, istream::gcount


istream::getline

istream& getline( char* pch, int nCount, char delim = '\n' );

istream& getline( unsigned char* puch, int nCount, char delim = '\n' );

istream& getline( signed char* psch, int nCount, char delim = '\n' );

Parameters

pch, puch, psch

A pointer to a character array.

nCount

The maximum number of characters to store, including the terminating NULL.

delim

The delimiter character (defaults to newline).

Remarks

Extracts characters from the stream until either the delimiter delim is found, the limit nCount–1 is reached, or end of file is reached. The characters are stored in the specified array followed by a null terminator. If the delimiter is found, it is extracted but not stored.

The get function, in contrast, neither extracts nor stores the delimiter.

istream Overview | Input Stream Classes

See Also istream::get, istream::read


istream::ignore

istream& ignore( int nCount = 1, int delim = EOF );

Parameters

nCount

The maximum number of characters to extract.

delim

The delimiter character (defaults to EOF).

Remarks

Extracts and discards up to nCount characters. Extraction stops if the delimiter delim is extracted or the end of file is reached. If delim = EOF (the default), then only the end of file condition causes termination. The delimiter character is extracted.


istream::ipfx

int ipfx( int need = 0 );

Return Value

A nonzero return value if the operation was successful; 0 if the stream’s error state is nonzero, in which case the function does nothing.

Parameter

need

Zero if called from formatted input functions; otherwise the minimum number of characters needed.

Remarks

This input prefix function is called by input functions prior to extracting data from the stream. Formatted input functions call ipfx( 0 ), while unformatted input functions usually call ipfx( 1 ).

Any ios object tied to this stream is flushed if need = 0 or if there are fewer than need characters in the input buffer. Also, ipfx extracts leading white space if ios::skipws is set.

istream Overview | Input Stream Classes

See Also istream::isfx


istream::isfx

void isfx();

Remarks

This input suffix function is called at the end of every extraction operation.


istream::istream

Public

istream( streambuf* psb );

END Public

Protected

istream( );

END Protected

Parameter

psb

A pointer to an existing object of a streambuf-derived class.

Remarks

Constructs an object of type istream.

istream Overview | Input Stream Classes

See Also ios::init


istream::~istream

virtual ~istream();

Remarks

Virtual destructor for the istream class.


istream::peek

int peek();

Return Value

Returns the next character without extracting it from the stream. Returns EOF if the stream is at end of file or if the ipfx function indicates an error.


istream::putback

istream& putback( char ch );

Parameter

ch

The character to put back; must be the character previously extracted.

Remarks

Puts a character back into the input stream. The putback function may fail and set the error state. If ch does not match the character that was previously extracted, the result is undefined.


istream::read

istream& read( char* pch, int nCount );

istream& read( unsigned char* puch, int nCount );

istream& read( signed char* psch, int nCount );

Parameters

pch, puch, psch

A pointer to a character array.

nCount

The maximum number of characters to read.

Remarks

Extracts bytes from the stream until the limit nCount is reached or until the end of file is reached. The read function is useful for binary stream input.

istream Overview | Input Stream Classes

See Also istream::get, istream::getline, istream::gcount, istream::ignore


istream::seekg

istream& seekg( streampos pos );

istream& seekg( streamoff off, ios::seek_dir dir );

Parameters

pos

The new position value; streampos is a typedef equivalent to long.

off

The new offset value; streamoff is a typedef equivalent to long.

dir

The seek direction. Must be one of the following enumerators:

  • ios::beg Seek from the beginning of the stream.

  • ios::cur Seek from the current position in the stream.

  • ios::end Seek from the end of the stream.

Remarks

Changes the get pointer for the stream. Not all derived classes of istream need support positioning; it is most often used with file-based streams.

istream Overview | Input Stream Classes

See Also istream::tellg, ostream::seekp, ostream::tellp


istream::sync

int sync();

Synchronizes the stream’s internal buffer with the external source of characters.

Return Value

EOF to indicate errors.

Remarks

Synchronizes the stream’s internal buffer with the external source of characters. This function calls the virtual streambuf::sync function so you can customize its implementation by deriving a new class from streambuf.

istream Overview | Input Stream Classes

See Also streambuf::sync


istream::tellg

streampos tellg();

Gets the value for the stream’s get pointer.

Return Value

A streampos type, corresponding to a long.

istream Overview | Input Stream Classes

See Also istream::seekg, ostream::tellp, ostream::seekp


istream::operator >>

istream& operator >>( char* psz );

istream& operator >>( unsigned char* pusz );

istream& operator >>( signed char* pssz );

istream& operator >>( char& rch );

istream& operator >>( unsigned char& ruch );

istream& operator >>( signed char& rsch );

istream& operator >>( short& s );

istream& operator >>( unsigned short& us );

istream& operator >>( int& n );

istream& operator >>( unsigned int& un );

istream& operator >>( long& l );

istream& operator >>( unsigned long& ul );

istream& operator >>( float& f );

istream& operator >>( double& d );

istream& operator >>( long double& ld ); (16-bit only)

istream& operator >>( streambuf* psb );

istream& operator >>( istream& (*fcn)(istream&) );

istream& operator >>( ios& (*fcn)(ios&) );

Remarks

These overloaded operators extract their argument from the stream. With the last two variations, you can use manipulators that are defined for both istream and ios.


istream& ws

ws

Remarks

Extracts leading white space from the stream by calling the eatwhite function.

istream Overview | Input Stream Classes

See Also istream::eatwhite


istream_withassign

#include <iostream.h>

The istream_withassign class is a variant of istream that allows object assignment. The predefined object cin is an object of this class and thus may be reassigned at run time to a different istream object. For example, a program that normally expects input from stdin could be temporarily directed to accept its input from a disk file.

Predefined Objects

The cin object is a predefined object of class ostream_withassign. It is connected to stdin (standard input, file descriptor 0).

The objects cin, cerr, and clog are tied to cout so that use of any of these may cause cout to be flushed.

Construction/Destruction — Public Members

istream_withassign

Constructs an istream_withassign object.

~istream_withassign

Destroys an istream_withassign object.

Operators — Public Members

operator =

Indicates an assignment operator.

Input Stream Classes

See Also ostream_withassign


istream_withassign::istream_withassign

istream_withassign( streambuf* psb );

istream_withassign();

Parameter

psb

A pointer to an existing object of a streambuf-derived class.

Remarks

The first constructor creates a ready-to-use object of type istream_withassign, complete with attached streambuf object.

The second constructor creates an object but does not initialize it. You must subsequently use the second variation of the istream_withassign assignment operator to attach the streambuf object, or use the first variation to initialize this object to match the specified istream object.

istream_withassign Overview | Input Stream Classes

See Also istream_withassign::operator =


istream_withassign::~istream_withassign

~istream_withassign();

Remarks

Destructor for the istream_withassign class.


istream_withassign::operator =

istream& operator =( const istream& ris );

istream& operator =( streambuf* psb );

Remarks

The first overloaded assignment operator assigns the specified istream object to this istream_withassign object.

The second operator attaches a streambuf object to an existing istream_withassign object, and it initializes the state of the istream_withassign object. This operator is often used in conjunction with the void-argument constructor.

Example

char buffer[100];
class xistream; // A special-purpose class derived from istream
extern xistream xin; // An xistream object constructed elsewhere

cin = xin; // cin is reassigned to xin
cin >> buffer; // xin used instead of cin

Example

char buffer[100];
extern filedesc fd; // A file descriptor for an open file
filebuf fb( fd ); // Construct a filebuf attached to fd

cin = &fb;     // fb associated with cin
cin >> buffer; // cin now gets its intput from the fb file

istream_withassign Overview | Input Stream Classes

See Also istream_withassign::istream_withassign


istrstream

#include <strstrea.h>

The istrstream class supports input streams that have character arrays as a source. You must allocate a character array before constructing an istrstream object. You can use istream operators and functions on this character data. A get pointer, working in the attached strstreambuf class, advances as you extract fields from the stream’s array. Use istream::seekg to go backwards. If the get pointer reaches the end of the string (and sets the ios::eof flag), you must call clear before seekg.

Construction/Destruction — Public Members

istrstream

Constructs an istrstream object.

~istrstream

Destroys an istrstream object.

Other Functions — Public Members

rdbuf

Returns a pointer to the stream’s associated strstreambuf object.

str

Returns a character array pointer to the string stream’s contents.

Input Stream Classes

See Also strstreambuf, streambuf, strstream, ostrstream


istrstream::istrstream

istrstream( char* psz );

istrstream( char* pch, int nLength );

Parameters

psz

A null-terminated character array (string).

pch

A character array that is not necessarily null terminated.

nLength

Size (in characters) of pch. If 0, then pch is assumed to point to a null-terminated array; if less than 0, then the array length is assumed to be unlimited.

Remarks

The first constructor uses the specified psz buffer to make an istrstream object with length corresponding to the string length.

The second constructor makes an istrstream object out of the first nLength characters of the pch buffer.

Both constructors automatically construct a strstreambuf object that manages the specified character buffer.


istrstream::~istrstream

~istrstream();

Remarks

Destroys an istrstream object and its associated strstreambuf object. The character buffer is not released because it was allocated by the user prior to istrstream construction.


istrstream::rdbuf

strstreambuf* rdbuf() const;

Return Value

Returns a pointer to the strstreambuf buffer object that is associated with this stream. Note that this is not the character buffer itself; the strstreambuf object contains a pointer to the character area.

istrstream Overview | Input Stream Classes

See Also istrstream::str


istrstream::str

char* str();

Return Value

Returns a pointer to the string stream’s character array. This pointer corresponds to the array used to construct the istrstream object.

istrstream Overview | Input Stream Classes

See Also istrstream::istrstream


ofstream

#include <fstream.h>

The ofstream class is an ostream derivative specialized for disk file output. All of its constructors automatically create and associate a filebuf buffer object.

The filebuf class documentation describes the get and put areas and their associated pointers. Only the put area and the put pointer are active for the ofstream class.

Construction/Destruction — Public Members

ofstream

Constructs an ofstream object.

~ofstream

Destroys an ofstream object.

Operations — Public Members

open

Opens a file and attaches it to the filebuf object and thus to the stream.

close

Flushes any waiting output and closes the stream’s file.

setbuf

Associates the specified reserve area to the stream’s filebuf object.

setmode

Sets the stream’s mode to binary or text.

attach

Attaches the stream (through the filebuf object) to an open file.

Status/Information — Public Members

rdbuf

Gets the stream’s filebuf object.

fd

Returns the file descriptor associated with the stream.

is_open

Tests whether the stream’s file is open.

Output Stream Classes

See Also filebuf, streambuf, ifstream, fstream


ofstream::attach

void attach( filedesc fd );

Parameter

fd

A file descriptor as returned by a call to the run-time function _open or _sopen; filedesc is a typedef equivalent to int.

Remarks

Attaches this stream to the open file specified by fd. The function fails when the stream is already attached to a file. In that case, the function sets ios::failbit in the stream’s error state.

ofstream Overview | Output Stream Classes

See Also filebuf::attach, ofstream::fd


ofstream::close

void close();

Remarks

Calls the close member function for the associated filebuf object. This function, in turn, flushes any waiting output, closes the file, and disconnects the file from the filebuf object. The filebuf object is not destroyed.

The stream’s error state is cleared unless the call to filebuf::close fails.

ofstream Overview | Output Stream Classes

See Also filebuf::close, ofstream::open, ofstream::is_open


ofstream::fd

filedesc fd() const;

Return Value

Returns the file descriptor associated with the stream. filedesc is a typedef equivalent to int. Its value is supplied by the underlying file system.

ofstream Overview | Output Stream Classes

See Also filebuf::fd, ofstream::attach


ofstream::is_open

int is_open() const;

Return Value

Returns a nonzero value if this stream is attached to an open disk file identified by a file descriptor; otherwise 0.

ofstream Overview | Output Stream Classes

See Also filebuf::is_open, ofstream::open, ofstream::close


ofstream::ofstream

ofstream();

ofstream( const char* szName, int nMode = ios::out, int nProt = filebuf::openprot );

ofstream( filedesc fd );

ofstream( filedesc fd, char* pch, int nLength );

Parameters

szName

The name of the file to be opened during construction.

nMode

An integer that contains mode bits defined as ios enumerators that can be combined with the bitwise OR ( | ) operator. The nMode parameter must have one of the following values:

  • ios::app The function performs a seek to the end of file. When new bytes are written to the file, they are always appended to the end, even if the position is moved with the ostream::seekp function.

  • ios::ate The function performs a seek to the end of file. When the first new byte is written to the file, it is appended to the end, but when subsequent bytes are written, they are written to the current position.

  • ios::in If this mode is specified, then the original file (if it exists) will not be truncated.

  • ios::out The file is opened for output (implied for all ofstream objects).

  • ios::trunc If the file already exists, its contents are discarded. This mode is implied if ios::out is specified and ios::ate, ios::app, and ios:in are not specified.

  • ios::nocreate If the file does not already exist, the function fails.

  • ios::noreplace If the file already exists, the function fails.

  • ios::binary Opens the file in binary mode (the default is text mode).

nProt

The file protection specification; defaults to the static integer filebuf::openprot that is equivalent to filebuf::sh_compat. The possible nProt values are:

  • filebuf::sh_compat Compatibility share mode.

  • filebuf::sh_none Exclusive mode; no sharing.

  • filebuf::sh_read Read sharing allowed.

  • filebuf::sh_write Write sharing allowed.

    To combine the filebuf::sh_read and filebuf::sh_write modes, use the logical OR ( || ) operator.

fd

A file descriptor as returned by a call to the run-time function _open or _sopen; filedesc is a typedef equivalent to int.

pch

Pointer to a previously allocated reserve area of length nLength. A NULL value (or nLength = 0) indicates that the stream will be unbuffered.

nLength

The length (in bytes) of the reserve area (0 = unbuffered).

Remarks

The four ofstream constructors are:

Constructor | Description
ofstream() | Constructs an ofstream object without opening a file.
ofstream( const char*, int, int ) | Contructs an ofstream object, opening the specified file.
ofstream( filedesc ) | Constructs an ofstream object that is attached to an open file.
ofstream( filedesc, char*, int ) | Constructs an ofstream object that is associated with a filebuf object. The filebuf object is attached to an open file and to a specified reserve area.

All ofstream constructors construct a filebuf object. The first three use an internally allocated reserve area, but the fourth uses a user-allocated area. The user-allocated area is not automatically released during destruction.


ofstream::~ofstream

~ofstream();

Remarks

Flushes the buffer, then destroys an ofstream object along with its associated filebuf object. The file is closed only if was opened by the constructor or by the open member function.

The filebuf destructor releases the reserve buffer only if it was internally allocated.


ofstream::open

void open( const char* szName, int nMode = ios::out, int nProt = filebuf::openprot );

Parameters

szName

The name of the file to be opened during construction.

nMode

An integer containing mode bits defined as ios enumerators that can be combined with the OR ( | ) operator. See the ofstream constructor for a list of the enumerators. The ios::out mode is implied.

nProt

The file protection specification; defaults to the static integer filebuf::openprot. See the ofstream constructor for a list of the other allowed values.

Remarks

Opens a disk file and attaches it to the stream’s filebuf object. If the filebuf object is already attached to an open file, or if a filebuf call fails, the ios::failbit is set. If the file is not found, the ios::failbit is set only if the ios::nocreate mode was used.

ofstream Overview | Output Stream Classes

See Also filebuf::open, ofstream::ofstream, ofstream::close, ofstream::is_open


ofstream::rdbuf

filebuf* rdbuf() const;

Return Value

Returns a pointer to the filebuf buffer object that is associated with this stream. (Note that this is not the character buffer; the filebuf object contains a pointer to the character area.)

Example

extern ofstream ofs;
int fd = ofs.rdbuf()->fd(); // Get the file descriptor for ofs


ofstream::setbuf

streambuf* setbuf( char* pch, int nLength );

Attaches the specified reserve area to the stream’s filebuf object.

Return Value

If the file is open and a buffer has already been allocated, the function returns NULL; otherwise it returns a pointer to the filebuf cast as a streambuf. The reserve area will not be released by the destructor.

Parameters

pch

A pointer to a previously allocated reserve area of length nLength. A NULL value indicates an unbuffered stream.

nLength

The length (in bytes) of the reserve area. A length of 0 indicates an unbuffered stream.


ofstream::setmode

int setmode( int nMode = filebuf::text );

Return Value

The previous mode; –1 if the parameter is invalid, the file is not open, or the mode cannot be changed.

Parameter

nMode

An integer that must be one of the following static filebuf constants:

  • filebuf::text Text mode (newline characters translated to and from carriage return – linefeed pairs).

  • filebuf::binary Binary mode (no translation).

Remarks

This function sets the binary/text mode of the stream’s filebuf object. It may be called only after the file is opened.

ofstream Overview | Output Stream Classes

See Also ios binary manipulator, ios text manipulator


ostream

#include <iostream.h>

The ostream class provides the basic capability for sequential and random-access output. An ostream object has a streambuf-derived object attached, and the two classes work together; the ostream class does the formatting, and the streambuf class does the low-level buffered output.

You can use ostream objects for sequential disk output if you first construct an appropriate filebuf object. (The filebuf class is derived from streambuf.) More often, you will use the predefined stream objects cout, cerr, and clog (actually objects of class ostream_withassign), or you will use objects of classes ofstream (disk file streams) and ostrstream (string streams).

All of the ostream member functions write unformatted data; formatted output is handled by the insertion operators.

Derivation

It is not always necessary to derive from ostream to add functionality to a stream; consider deriving from streambuf instead, as illustrated in Deriving Your Own Stream Classes. The ofstream and ostrstream classes are examples of ostream-derived classes that construct member objects of predetermined derived streambuf classes. You can add manipulators without deriving a new class.

If you add new insertion operators for a derived ostream class, then the rules of C++ dictate that you must reimplement all the base class insertion operators. If, however, you reimplement the operators through inline equivalence, no extra code will be generated.

Construction/Destruction — Public Members

ostream

Constructs an ostream object that is attached to an existing streambuf object.

~ostream

Destroys an ostream object.

Prefix/Suffix Functions — Public Members

opfx

Output prefix function, called prior to insertion operations to check for error conditions, and so forth.

osfx

Output suffix function, called after insertion operations; flushes the stream’s buffer if it is unit buffered.

Unformatted Output — Public Members

put

Inserts a single byte into the stream.

write

Inserts a series of bytes into the stream.

Other Functions — Public Members

flush

Flushes the buffer associated with this stream.

seekp

Changes the stream’s put pointer.

tellp

Gets the value of the stream’s put pointer.

Operators — Public Members

operator <<

Insertion operator for various types.

Manipulators

endl

Inserts a newline sequence and flushes the buffer.

ends

Inserts a null character to terminate a string.

flush

Flushes the stream’s buffer.

Output Stream Classes

See Also streambuf, ofstream, ostrstream, cout, cerr, clog

Example

class xstream : public ostream
{
public:
    // Constructors, etc.
    // ........
    inline xstream& operator << ( char ch ) // insertion for char
    {
          return (xstream&)ostream::operator << ( ch );
    }
    // ........
    // Insertions for other types
};


ostream::flush

ostream& flush();

Remarks

Flushes the buffer associated with this stream. The flush function calls the sync function of the associated streambuf.

ostream Overview | Output Stream Classes

See Also ostream flush manipulator, streambuf::sync


ostream::opfx

int opfx();

Return Value

If the ostream object’s error state is not 0, opfx returns 0 immediately; otherwise it returns a nonzero value.

Remarks

This output prefix function is called before every insertion operation. If another ostream object is tied to this stream, the opfx function flushes that stream.


ostream::osfx

void osfx();

Remarks

This output suffix function is called after every insertion operation. It flushes the ostream object if ios::unitbuf is set, or stdout and stderr if ios::stdio is set.


ostream::ostream

Public

ostream( streambuf* psb );

END Public

Protected

ostream( );

END Protected

Parameter

psb

A pointer to an existing object of a streambuf-derived class.

Remarks

Constructs an object of type ostream.

ostream Overview | Output Stream Classes

See Also ios::init


ostream::~ostream

virtual ~ostream();

Remarks

Destroys an ostream object. The output buffer is flushed as appropriate. The attached streambuf object is destroyed only if it was allocated internally within the ostream constructor.


ostream::put

ostream& put( char ch );

Parameter

ch

The character to insert.

Remarks

This function inserts a single character into the output stream.


ostream::seekp

ostream& seekp( streampos pos );

ostream& seekp( streamoff off, ios::seek_dir dir );

Parameters

pos

The new position value; streampos is a typedef equivalent to long.

off

The new offset value; streamoff is a typedef equivalent to long.

dir

The seek direction specified by the enumerated type ios::seek_dir, with values including:

  • ios::beg Seek from the beginning of the stream.

  • ios::cur Seek from the current position in the stream.

  • ios::end Seek from the end of the stream.

Remarks

Changes the position value for the stream. Not all derived classes of ostream need support positioning. For file streams, the position is the byte offset from the beginning of the file; for string streams, it is the byte offset from the beginning of the string.

ostream Overview | Output Stream Classes

See Also ostream::tellp, istream::seekg, istream::tellg


ostream::tellp

streampos tellp();

Return Value

A streampos type that corresponds to a long.

Remarks

Gets the position value for the stream. Not all derived classes of ostream need support positioning. For file streams, the position is the byte offset from the beginning of the file; for string streams, it is the byte offset from the beginning of the string. Gets the value for the stream’s put pointer.

ostream Overview | Output Stream Classes

See Also ostream::seekp, istream::tellg, istream::seekg


ostream::write

ostream& write( const char* pch, int nCount );

ostream& write( const unsigned char* puch, int nCount );

ostream& write( const signed char* psch, int nCount );

Parameters

pch, puch, psch

A pointer to a character array.

nCount

The number of characters to be written.

Remarks

Inserts a specified number of bytes from a buffer into the stream. If the underlying file was opened in text mode, additional carriage return characters may be inserted. The write function is useful for binary stream output.


ostream::operator <<

ostream& operator <<( char ch );

ostream& operator <<( unsigned char uch );

ostream& operator <<( signed char sch );

ostream& operator <<( const char* psz );

ostream& operator <<( const unsigned char* pusz );

ostream& operator <<( const signed char* pssz );

ostream& operator <<( short s );

ostream& operator <<( unsigned short us );

ostream& operator <<( int n );

ostream& operator <<( unsigned int un );

ostream& operator <<( long l );

ostream& operator <<( unsigned long ul );

ostream& operator <<( float f );

ostream& operator <<( double d );

ostream& operator <<( long double ld ); (16-bit only)

ostream& operator <<( const void* pv );

ostream& operator <<( streambuf* psb );

ostream& operator <<( ostream& (*fcn)(ostream&) );

ostream& operator <<( ios& (*fcn)(ios&) );

Remarks

These overloaded operators insert their argument into the stream. With the last two variations, you can use manipulators that are defined for both ostream and ios.


ostream& endl

endl

Remarks

This manipulator, when inserted into an output stream, inserts a newline character and then flushes the buffer.


ostream& ends

ends

Remarks

This manipulator, when inserted into an output stream, inserts a null-terminator character. It is particularly useful for ostrstream objects.


ostream& flush

flush

Remarks

This manipulator, when inserted into an output stream, flushes the output buffer by calling the streambuf::sync member function.

ostream Overview | Output Stream Classes

See Also ostream::flush, streambuf::sync


ostream_withassign

#include <iostream.h>

The ostream_withassign class is a variant of ostream that allows object assignment. The predefined objects cout, cerr, and clog are objects of this class and thus may be reassigned at run time to a different ostream object. For example, a program that normally sends output to stdout could be temporarily directed to send its output to a disk file.

Predefined Objects

The three predefined objects of class ostream_withassign are connected as follows:

cout

Standard output (file descriptor 1).

cerr

Unit buffered standard error (file descriptor 2).

clog

Fully buffered standard error (file descriptor 2).

Unit buffering, as used by cerr, means that characters are flushed after each insertion operation. The objects cin, cerr, and clog are tied to cout so that use of any of these will cause cout to be flushed.

Construction/Destruction — Public Members

ostream_withassign

Constructs an ostream_withassign object.

~ostream_withassign

Destroys an ostream_withassign object.

Operators — Public Members

operator =

Assignment operator.

Output Stream Classes

See Also istream_withassign


ostream_withassign::ostream_withassign

ostream_withassign( streambuf* psb );

ostream_withassign();

Parameter

psb

A pointer to an existing object of a streambuf-derived class.

Remarks

The first constructor makes a ready-to-use object of type ostream_withassign, with an attached streambuf object.

The second constructor makes an object but does not initialize it. You must subsequently use the streambuf assignment operator to attach the streambuf object, or use the ostream assignment operator to initialize this object to match the specified object.

ostream Overview | Output Stream Classes

See Also ostream_withassign::operator =


ostream_withassign::~ostream_withassign

~ostream_withassign();

Remarks

Destructor for the ostream_withassign class.


ostream_withassign::operator =

ostream& operator =( const ostream&_os );

ostream& operator =( streambuf*_sp );

Remarks

The first overloaded assignment operator assigns the specified ostream object to this ostream_withassign object.

The second operator attaches a streambuf object to an existing ostream_withassign object, and initializes the state of the ostream_withassign object. This operator is often used in conjunction with the void-argument constructor.

Example

filebuf fb( "test.dat" ); // Filebuf object attached to "test.dat"
cout = &fb;         // fb associated with cout
cout << "testing"; // Message goes to "test.dat" instead of stdout

ostream Overview | Output Stream Classes

See Also ostream_withassign::ostream_withassign, cout


ostrstream

#include <strstrea.h>

The ostrstream class supports output streams that have character arrays as a destination. You can allocate a character array prior to construction, or the constructor can internally allocate an expandable array. You can then use all the ostream operators and functions to fill the array.

Be aware that there is a put pointer working behind the scenes in the attached strstreambuf class. This pointer advances as you insert fields into the stream’s array. The only way you can make it go backward is to use the ostream::seekp function. If the put pointer reaches the end of user-allocated memory (and sets the ios::eof flag), you must call clear before seekp.

Construction/Destruction — Public Members

ostrstream

Constructs an ostrstream object.

~ostrstream

Destroys an ostrstream object.

Other Functions — Public Members

pcount

Returns the number of bytes that have been stored in the stream’s buffer.

rdbuf

Returns a pointer to the stream’s associated strstreambuf object.

str

Returns a character array pointer to the string stream’s contents and freezes the array.

Output Stream Classes

See Also strstreambuf, streambuf, strstream, istrstream


ostrstream::ostrstream

ostrstream();

ostrstream( char* pch, int nLength, int nMode = ios::out );

Parameters

pch

A character array that is large enough to accommodate future output stream activity.

nLength

The size (in characters) of pch. If 0, then pch is assumed to point to a null-terminated array and strlen( pch ) is used as the length; if less than 0, the array is assumed to have infinite length.

nMode

The stream-creation mode, which must be one of the following enumerators as defined in class ios:

  • ios::out Default; storing begins at pch.

  • ios::ate The pch parameter is assumed to be a null-terminated array; storing begins at the NULL character.

  • ios::app Same as ios::ate.

Remarks

The first constructor makes an ostrstream object that uses an internal, dynamic buffer.

The second constructor makes an ostrstream object out of the first nLength characters of the pch buffer. The stream will not accept characters once the length reaches nLength.


ostrstream::~ostrstream

~ostrstream();

Remarks

Destroys an ostrstream object and its associated strstreambuf object, thus releasing all internally allocated memory. If you used the void-argument constructor, the internally allocated character buffer is released; otherwise, you must release it.

An internally allocated character buffer will not be released if it was previously frozen by an str or strstreambuf::freeze function call.

ostrstream Overview | Output Stream Classes

See Also ostrstream::str, strstreambuf::freeze


ostrstream::pcount

int pcount() const;

Return Value

Returns the number of bytes stored in the buffer. This information is especially useful when you have stored binary data in the object.


ostrstream::rdbuf

strstreambuf* rdbuf() const;

Return Value

Returns a pointer to the strstreambuf buffer object that is associated with this stream. This is not the character buffer; the strstreambuf object contains a pointer to the character area.

ostrstream Overview | Output Stream Classes

See Also ostrstream::str


ostrstream::str

char* str();

Return Value

Returns a pointer to the internal character array. If the stream was built with the void-argument constructor, str freezes the array. You must not send characters to a frozen stream, and you are responsible for deleting the array. You can, however, subsequently unfreeze the array by calling rdbuf->freeze( 0 ).

If the stream was built with the constructor that specified the buffer, the pointer contains the same address as the array used to construct the ostrstream object.

ostrstream Overview | Output Stream Classes

See Also ostrstream::ostrstream, ostrstream::rdbuf, strstreambuf::freeze


stdiobuf

#include <stdiostr.h>

The run-time library supports three conceptual sets of I/O functions: iostreams (C++ only), standard I/O (the functions declared in STDIO.H), and low-level I/O (the functions declared in IO.H). The stdiobuf class is a derived class of streambuf that is specialized for buffering to and from the standard I/O system.

Because the standard I/O system does its own internal buffering, the extra buffering level provided by stdiobuf may reduce overall input/output efficiency. The stdiobuf class is useful when you need to mix iostream I/O with standard I/O (printf and so forth).

You can avoid use of the stdiobuf class if you use the filebuf class. You must also use the stream class’s ios::flags member function to set the ios::stdio format flag value.

Construction/Destruction — Public Members

stdiobuf

Constructs a stdiobuf object from a FILE pointer.

~stdiobuf

Destroys a stdiobuf object.

Other Functions — Public Members

stdiofile

Gets the file that is attached to the stdiofile object.

Stream Buffer Classes

See Also stdiostream, filebuf, strstreambuf, ios::flags


stdiobuf::stdiobuf

stdiobuf( FILE* fp );

Parameter

fp

A standard I/O file pointer (can be obtained through an fopen or _fsopen call).

Remarks

Objects of class stdiobuf are constructed from open standard I/O files, including stdin, stdout, and stderr. The object is unbuffered by default.


stdiobuf::~stdiobuf

~stdiobuf();

Remarks

Destroys a stdiobuf object and, in the process, flushes the put area. The destructor does not close the attached file.


stdiobuf::stdiofile

FILE* stdiofile();

Remarks

Returns the standard I/O file pointer associated with a stdiobuf object.


stdiostream

#include <stdiostr.h>

The stdiostream class makes I/O calls (through the stdiobuf class) to the standard I/O system, which does its own internal buffering. Calls to the functions declared in STDIO.H, such as printf, can be mixed with stdiostream I/O calls.

This class is included for compatibility with earlier stream libraries. You can avoid use of the stdiostream class if you use the ostream or istream class with an associated filebuf class. You must also use the stream class’s ios::flags member function to set the ios::stdio format flag value.

The use of the stdiobuf class may reduce efficiency because it imposes an extra level of buffering. Do not use this feature unless you need to mix iostream library calls with standard I/O calls for the same file.

Construction/Destruction — Public Members

stdiostream

Constructs a stdiostream object that is associated with a standard I/O FILE pointer.

~stdiostream

Destroys a stdiostream object (virtual).

Other Functions — Public Members

rdbuf

Gets the stream’s stdiobuf object.

Input/Output Stream Classes

See Also stdiobuf, ios::flags


stdiostream::rdbuf

stdiobuf* rdbuf() const;

Return Value

Returns a pointer to the stdiobuf buffer object that is associated with this stream. The rdbuf function is useful when you need to call stdiobuf member functions.


stdiostream::stdiostream

stdiostream( FILE* fp );

Parameter

fp

A standard I/O file pointer (can be obtained through an fopen or _fsopen call). Could be stdin, stdout, or stderr.

Remarks

Objects of class stdiostream are constructed from open standard I/O files. An unbuffered stdiobuf object is automatically associated, but the standard I/O system provides its own buffering.

stdiostream Overview | Input/Output Stream Classes

Example

stdiostream myStream( stdout );


stdiostream::~stdiostream

~stdiostream();

Remarks

This destructor destroys the stdiobuf object associated with this stream; however, the attached file is not closed.


streambuf

#include <iostream.h>

All the iostream classes in the ios hierarchy depend on an attached streambuf class for the actual I/O processing. This class is an abstract class, but the iostream class library contains the following derived buffer classes for use with streams:

  • filebuf Buffered disk file I/O.

  • strstreambuf Stream data held entirely within an in-memory byte array.

  • stdiobuf Disk I/O with buffering done by the underlying standard I/O system.

All streambuf objects, when configured for buffered processing, maintain a fixed memory buffer, called a reserve area, that can be dynamically partitioned into a get area for input, and a put area for output. These areas may or may not overlap. With the protected member functions, you can access and manipulate a get pointer for character retrieval and a put pointer for character storage. The exact behavior of the buffers and pointers depends on the implementation of the derived class.

The capabilities of the iostream classes can be extended significantly through the derivation of new streambuf classes. The ios class tree supplies the programming interface and all formatting features, but the streambuf class does the real work. The ios classes call the streambuf public members, including a set of virtual functions.

The streambuf class provides a default implementation of certain virtual member functions. The “Default Implementation” section for each such function suggests function behavior for the derived class.

Character Input Functions — Public Members

in_avail

Returns the number of characters in the get area.

sgetc

Returns the character at the get pointer, but does not move the pointer.

snextc

Advances the get pointer, then returns the next character.

sbumpc

Returns the current character, and then advances the get pointer.

stossc

Moves the get pointer forward one position, but does not return a character.

sputbackc

Attempts to move the get pointer back one position.

sgetn

Gets a sequence of characters from the streambuf object’s buffer.

Character Output Functions — Public Members

out_waiting

Returns the number of characters in the put area.

sputc

Stores a character in the put area and advances the put pointer.

sputn

Stores a sequence of characters in the streambuf object’s buffer and advances the put pointer.

Construction/Destruction — Public Members

~streambuf

Virtual destructor.

Diagnostic Functions — Public Members

dbp

Prints buffer statistics and pointer values.

Virtual Functions — Public Members

sync

Empties the get area and the put area.

setbuf

Attempts to attach a reserve area to the streambuf object.

seekoff

Seeks to a specified offset.

seekpos

Seeks to a specified position.

overflow

Empties the put area.

underflow

Fills the get area if necessary.

pbackfail

Augments the sputbackc function.

Construction/Destruction — Protected Members

streambuf

Constructors for use in derived classes.

Other Protected Member Functions — Protected Members

base

Returns a pointer to the start of the reserve area.

ebuf

Returns a pointer to the end of the reserve area.

blen

Returns the size of the reserve area.

pbase

Returns a pointer to the start of the put area.

pptr

Returns the put pointer.

epptr

Returns a pointer to the end of the put area.

eback

Returns the lower bound of the get area.

gptr

Returns the get pointer.

egptr

Returns a pointer to the end of the get area.

setp

Sets all the put area pointers.

setg

Sets all the get area pointers.

pbump

Increments the put pointer.

gbump

Increments the get pointer.

setb

Sets up the reserve area.

unbuffered

Tests or sets the streambuf buffer state variable.

allocate

Allocates a buffer, if needed, by calling doalloc.

doallocate

Allocates a reserve area (virtual function).

Stream Buffer Classes

See Also streambuf::doallocate, streambuf::unbuffered


streambuf::allocate

Protected

int allocate();

END Protected

Return Value

Calls the virtual function doallocate to set up a reserve area. If a reserve area already exists or if the streambuf object is unbuffered, allocate returns 0. If the space allocation fails, allocate returns EOF.

streambuf Overview | Stream Buffer Classes

See Also streambuf::doallocate, streambuf::unbuffered


streambuf::base

Protected

char* base() const

END Protected

Return Value

Returns a pointer to the first byte of the reserve area. The reserve area consists of space between the pointers returned by base and ebuf.

streambuf Overview | Stream Buffer Classes

See Also streambuf::ebuf, streambuf::setb, streambuf::blen


streambuf::blen

Protected

int blen() const;

END Protected

Return Value

Returns the size, in bytes, of the reserve area.

streambuf Overview | Stream Buffer Classes

See Also streambuf::base, streambuf::ebuf, streambuf::setb


streambuf::dbp

void dbp();

Remarks

Writes ASCII debugging information directly on stdout. Treat this function as part of the protected interface.

streambuf Overview | Stream Buffer Classes

Example

STREAMBUF DEBUG INFO: this = 00E7:09DC
base()=00E7:0A0C, ebuf()=00E7:0C0C,  blen()=512
eback()=0000:0000, gptr()=0000:0000, egptr()=0000:0000
pbase()=00E7:0A0C, pptr()=00E7:0A22, epptr()=00E7:0C0C


streambuf::doallocate

Protected

virtual int doallocate();

END Protected

Return Value

Called by allocate when space is needed. The doallocate function must allocate a reserve area, then call setb to attach the reserve area to the streambuf object. If the reserve area allocation fails, doallocate returns EOF.

Remarks

By default, this function attempts to allocate a reserve area using operator new.

streambuf Overview | Stream Buffer Classes

See Also streambuf::allocate, streambuf::setb


streambuf::eback

Protected

char* eback() const;

END Protected

Return Value

Returns the lower bound of the get area. Space between the eback and gptr pointers is available for putting a character back into the stream.

streambuf Overview | Stream Buffer Classes

See Also streambuf::sputbackc, streambuf::gptr


streambuf::ebuf

Protected

char* ebuf() const;

END Protected

Return Value

Returns a pointer to the byte after the last byte of the reserve area. The reserve area consists of space between the pointers returned by base and ebuf.

streambuf Overview | Stream Buffer Classes

See Also streambuf::base, streambuf::setb, streambuf::blen


streambuf::egptr

Protected

char* egptr() const;

END Protected

Return Value

Returns a pointer to the byte after the last byte of the get area.

streambuf Overview | Stream Buffer Classes

See Also streambuf::setg, streambuf::eback, streambuf::gptr


streambuf::epptr

Protected

char* epptr() const;

END Protected

Return Value

Returns a pointer to the byte after the last byte of the put area.

streambuf Overview | Stream Buffer Classes

See Also streambuf::setp, streambuf::pbase, streambuf::pptr


streambuf::gbump

Protected

void gbump( int nCount );

END Protected

Parameter

Count

The number of bytes to increment the get pointer. May be positive or negative.

Remarks

Increments the get pointer. No bounds checks are made on the result.

streambuf Overview | Stream Buffer Classes

See Also streambuf::pbump


streambuf::gptr

Protected

char* gptr() const;

END Protected

Return Value

Returns a pointer to the next character to be fetched from the streambuf buffer. This pointer is known as the get pointer.

streambuf Overview | Stream Buffer Classes

See Also streambuf::setg, streambuf::eback, streambuf::egptr


streambuf::in_avail

int in_avail() const;

Return Value

Returns the number of characters in the get area that are available for fetching. These characters are between the gptr and egptr pointers and may be fetched with a guarantee of no errors.


streambuf::out_waiting

int out_waiting() const;

Return Value

Returns the number of characters in the put area that have not been sent to the final output destination. These characters are between the pbase and pptr pointers.


streambuf::overflow

virtual int overflow( int nCh = EOF ) = 0;

Return Value

EOF to indicate an error.

Parameter

nCh

EOF or the character to output.

Remarks

The virtual overflow function, together with the sync and underflow functions, defines the characteristics of the streambuf-derived class. Each derived class might implement overflow differently, but the interface with the calling stream class is the same.

The overflow function is most frequently called by public streambuf functions like sputc and sputn when the put area is full, but other classes, including the stream classes, can call overflow anytime.

The function “consumes” the characters in the put area between the pbase and pptr pointers and then reinitializes the put area. The overflow function must also consume nCh (if nCh is not EOF), or it might choose to put that character in the new put area so that it will be consumed on the next call.

The definition of “consume” varies among derived classes. For example, the filebuf class writes its characters to a file, while the strsteambuf class keeps them in its buffer and (if the buffer is designated as dynamic) expands the buffer in response to a call to overflow. This expansion is achieved by freeing the old buffer and replacing it with a new, larger one. The pointers are adjusted as necessary.

Default Implementation

No default implementation. Derived classes must define this function.

streambuf Overview | Stream Buffer Classes

See Also streambuf::pbase, streambuf::pptr, streambuf::setp, streambuf::sync, streambuf::underflow


streambuf::pbackfail

virtual int pbackfail( int nCh );

Return Value

The nCh parameter if successful; otherwise EOF.

Parameter

nCh

The character used in a previous sputbackc call.

Remarks

This function is called by sputbackc if it fails, usually because the eback pointer equals the gptr pointer. The pbackfail function should deal with the situation, if possible, by such means as repositioning the external file pointer.

Default implementation

Returns EOF.

streambuf Overview | Stream Buffer Classes

See Also streambuf::sputbackc


streambuf::pbase

Protected

char* pbase() const;

END Protected

Return Value

Returns a pointer to the start of the put area. Characters between the pbase pointer and the pptr pointer have been stored in the buffer but not flushed to the final output destination.

streambuf Overview | Stream Buffer Classes

See Also streambuf::pptr, streambuf::setp, streambuf::out_waiting


streambuf::pbump

Protected

void pbump( int nCount );

END Protected

Parameter

nCount

The number of bytes to increment the put pointer. May be positive or negative.

Remarks

Increments the put pointer. No bounds checks are made on the result.

streambuf Overview | Stream Buffer Classes

See Also streambuf::gbump, streambuf::setp


streambuf::pptr

Protected

char* pptr() const;

END Protected

Return Value

Returns a pointer to the first byte of the put area. This pointer is known as the put pointer and is the destination for the next character(s) sent to the streambuf object.

streambuf Overview | Stream Buffer Classes

See Also streambuf::epptr, streambuf::pbase, streambuf::setp


streambuf::sbumpc

int sbumpc();

Return Value

Returns the current character, then advances the get pointer. Returns EOF if the get pointer is currently at the end of the sequence (equal to the egptr pointer).

streambuf Overview | Stream Buffer Classes

See Also streambuf::epptr, streambuf::gbump


streambuf::seekoff

virtual streampos seekoff( streamoff off, ios::seek_dir dir, int nMode = ios::in | ios::out );

Return Value

The new position value. This is the byte offset from the start of the file (or string). If both ios::in and ios::out are specified, the function returns the output position. If the derived class does not support positioning, the function returns EOF.

Parameters

off

The new offset value; streamoff is a typedef equivalent to long.

dir

One of the following seek directions specified by the enumerated type seek_dir:

  • ios::beg Seek from the beginning of the stream.

  • ios::cur Seek from the current position in the stream.

  • ios::end Seek from the end of the stream.

nMode

An integer that contains a bitwise OR ( | ) combination of the enumerators ios::in and ios::out.

Remarks

Changes the position for the streambuf object. Not all derived classes of streambuf need to support positioning; however, the filebuf, strstreambuf, and stdiobuf classes do support positioning.

Classes derived from streambuf often support independent input and output position values. The nMode parameter determines which value(s) is set.

Default Implementation

Returns EOF.

streambuf Overview | Stream Buffer Classes

See Also streambuf::seekpos


streambuf::seekpos

virtual streampos seekpos( streampos pos, int nMode = ios::in | ios::out );

Return Value

The new position value. If both ios::in and ios::out are specified, the function returns the output position. If the derived class does not support positioning, the function returns EOF.

Parameters

pos

The new position value; streampos is a typedef equivalent to long.

nMode

An integer that contains mode bits defined as ios enumerators that can be combined with the OR ( | ) operator. See ofstream::ofstream for a listing of the enumerators.

Remarks

Changes the position, relative to the beginning of the stream, for the streambuf object. Not all derived classes of streambuf need to support positioning; however, the filebuf, strstreambuf, and stdiobuf classes do support positioning.

Classes derived from streambuf often support independent input and output position values. The nMode parameter determines which value(s) is set.

Default Implementation

Calls seekoff( (streamoff) pos, ios::beg, nMode ). Thus, to define seeking in a derived class, it is usually necessary to redefine only seekoff.

streambuf Overview | Stream Buffer Classes

See Also streambuf::seekoff


streambuf::setb

Protected

void setb( char* pb, char* peb, int nDelete = 0 );

END Protected

Parameters

pb

The new value for the base pointer.

peb

The new value for the ebuf pointer.

nDelete

Flag that controls automatic deletion. If nDelete is not 0, the reserve area will be deleted when: (1) the base pointer is changed by another setb call, or (2) the streambuf destructor is called.

Remarks

Sets the values of the reserve area pointers. If both pb and peb are NULL, there is no reserve area. If pb is not NULL and peb is NULL, the reserve area has a length of 0.

streambuf Overview | Stream Buffer Classes

See Also streambuf::base, streambuf::ebuf


streambuf::setbuf

virtual streambuf* setbuf( char* pr, int nLength );

Return Value

A streambuf pointer if the buffer is accepted; otherwise NULL.

Parameters

pr

A pointer to a previously allocated reserve area of length nLength. A NULL value indicates an unbuffered stream.

nLength

The length (in bytes) of the reserve area. A length of 0 indicates an unbuffered stream.

Remarks

Attaches the specified reserve area to the streambuf object. Derived classes may or may not use this area.

Default Implementation

Accepts the request if there is not a reserved area already.


streambuf::setg

Protected

void setg( char* peb, char* pg, char* peg );

END Protected

Parameters

peb

The new value for the eback pointer.

pg

The new value for the gptr pointer.

peg

The new value for the egptr pointer.

Remarks

Sets the values for the get area pointers.

streambuf Overview | Stream Buffer Classes

See Also streambuf::eback, streambuf::gptr, streambuf::egptr


streambuf::setp

Protected

void setp( char* pp, char* pep );

END Protected

Parameters

pp

The new value for the pbase and pptr pointers.

pep

The new value for the epptr pointer.

Remarks

Sets the values for the put area pointers.

streambuf Overview | Stream Buffer Classes

See Also streambuf::pptr, streambuf::pbase, streambuf::epptr


streambuf::sgetc

int sgetc();

Remarks

Returns the character at the get pointer. The sgetc function does not move the get pointer. Returns EOF if there is no character available.

streambuf Overview | Stream Buffer Classes

See Also streambuf::sbumpc, streambuf::sgetn, streambuf::snextc, streambuf::stossc


streambuf::sgetn

int sgetn( char* pch, int nCount );

Return Value

The number of characters fetched.

Parameters

pch

A pointer to a buffer that will receive characters from the streambuf object.

nCount

The number of characters to get.

Remarks

Gets the nCount characters that follow the get pointer and stores them in the area starting at pch. When fewer than nCount characters remain in the streambuf object, sgetn fetches whatever characters remain. The function repositions the get pointer to follow the fetched characters.

streambuf Overview | Stream Buffer Classes

See Also streambuf::sbumpc, streambuf::sgetc, streambuf::snextc, streambuf::stossc


streambuf::snextc

int snextc();

Return Value

First tests the get pointer, then returns EOF if it is already at the end of the get area. Otherwise, it moves the get pointer forward one character and returns the character that follows the new position. It returns EOF if the pointer has been moved to the end of the get area.

streambuf Overview | Stream Buffer Classes

See Also streambuf::sbumpc, streambuf::sgetc, streambuf::sgetn, streambuf::stossc


streambuf::sputbackc

int sputbackc( char ch );

Return Value

EOF on failure.

Parameter

ch

The character to be put back to the streambuf object.

Remarks

Moves the get pointer back one character. The ch character must match the character just before the get pointer.

streambuf Overview | Stream Buffer Classes

See Also streambuf::sbumpc, streambuf::pbackfail


streambuf::sputc

int sputc( int nCh );

Return Value

The number of characters successfully stored; EOF on error.

Parameter

nCh

The character to store in the streambuf object.

Remarks

Stores a character in the put area and advances the put pointer.

This public function is available to code outside the class, including the classes derived from ios. A derived streambuf class can gain access to its buffer directly by using protected member functions.

streambuf Overview | Stream Buffer Classes

See Also streambuf::sputn


streambuf::sputn

int sputn( const char* pch, int nCount );

Return Value

The number of characters stored. This number is usually nCount but could be less if an error occurs.

Parameters

pch

A pointer to a buffer that contains data to be copied to the streambuf object.

nCount

The number of characters in the buffer.

Remarks

Copies nCount characters from pch to the streambuf buffer following the put pointer. The function repositions the put pointer to follow the stored characters.

streambuf Overview | Stream Buffer Classes

See Also streambuf::sputc


streambuf::stossc

void stossc();

Remarks

Moves the get pointer forward one character. If the pointer is already at the end of the get area, the function has no effect.

streambuf Overview | Stream Buffer Classes

See Also streambuf::sbumpc, streambuf::sgetn, streambuf::snextc, streambuf::sgetc


streambuf::streambuf

Protected

streambuf();

streambuf( char* pr, int nLength );

END Protected

Parameters

pr

A pointer to a previously allocated reserve area of length nLength. A NULL value indicates an unbuffered stream.

nLength

The length (in bytes) of the reserve area. A length of 0 indicates an unbuffered stream.

Remarks

The first constructor makes an uninitialized streambuf object. This object is not suitable for use until a setbuf call is made. A derived class constructor usually calls setbuf or uses the second constructor.

The second constructor initializes the streambuf object with the specified reserve area or marks it as unbuffered.

streambuf Overview | Stream Buffer Classes

See Also streambuf::setbuf


streambuf::~streambuf

Protected

virtual ~streambuf();

END Protected

Remarks

The streambuf destructor flushes the buffer if the stream is being used for output.


streambuf::sync

virtual int sync();

Return Value

EOF if an error occurs.

Remarks

The virtual sync function, with the overflow and underflow functions, defines the characteristics of the streambuf-derived class. Each derived class might implement sync differently, but the interface with the calling stream class is the same.

The sync function flushes the put area. It also empties the get area and, in the process, sends any unprocessed characters back to the source, if necessary.

Default Implementation

Returns 0 if the get area is empty and there are no more characters to output; otherwise, it returns EOF.

streambuf Overview | Stream Buffer Classes

See Also streambuf::overflow


streambuf::unbuffered

Protected

void unbuffered( int nState );

int unbuffered() const;

END Protected

Parameter

nState

The value of the buffering state variable; 0 = buffered, nonzero = unbuffered.

Remarks

The first overloaded unbuffered function sets the value of the streambuf object’s buffering state. This variable’s primary purpose is to control whether the allocate function automatically allocates a reserve area.

The second function returns the current buffering state variable.

streambuf Overview | Stream Buffer Classes

See Also streambuf::allocate, streambuf::doallocate


streambuf::underflow

mfvirtual int underflow() = 0;

Remarks

The virtual underflow function, with the sync and overflow functions, defines the characteristics of the streambuf-derived class. Each derived class might implement underflow differently, but the interface with the calling stream class is the same.

The underflow function is most frequently called by public streambuf functions like sgetc and sgetn when the get area is empty, but other classes, including the stream classes, can call underflow anytime.

The underflow function supplies the get area with characters from the input source. If the get area contains characters, underflow returns the first character. If the get area is empty, it fills the get area and returns the next character (which it leaves in the get area). If there are no more characters available, then underflow returns EOF and leaves the get area empty.

In the strstreambuf class, underflow adjusts the egptr pointer to access storage that was dynamically allocated by a call to overflow.

Default Implementation

No default implementation. Derived classes must define this function.


strstream

#include <strstrea.h>

The strstream class supports I/O streams that have character arrays as a source and destination. You can allocate a character array prior to construction, or the constructor can internally allocate a dynamic array. You can then use all the input and output stream operators and functions to fill the array.

Be aware that a put pointer and a get pointer are working independently behind the scenes in the attached strstreambuf class. The put pointer advances as you insert fields into the stream’s array, and the get pointer advances as you extract fields. The ostream::seekp function moves the put pointer, and the istream::seekg function moves the get pointer. If either pointer reaches the end of the string (and sets the ios::eof flag), you must call clear before seeking.

Construction/Destruction — Public Members

strstream

Constructs a strstream object.

~strstream

Destroys a strstream object.

Other Functions — Public Members

pcount

Returns the number of bytes that have been stored in the stream’s buffer.

rdbuf

Returns a pointer to the stream’s associated strstreambuf object.

str

Returns a pointer to the string stream’s character buffer and freezes it.

Input/Output Stream Classes

See Also strstreambuf, streambuf, istrstream, ostrstream


strstream::pcount

int pcount() const;

Return Value

Returns the number of bytes stored in the buffer. This information is especially useful when you have stored binary data in the object.


strstream::rdbuf

strstreambuf* rdbuf() const;

Return Value

Returns a pointer to the strstreambuf buffer object that is associated with this stream. This is not the character buffer; the strstreambuf object contains a pointer to the character area.

strstream Overview | Input/Output Stream Classes

See Also strstream::str


strstream::str

char* str();

Return Value

Returns a pointer to the internal character array. If the stream was built with the void-argument constructor, then str freezes the array. You must not send characters to a frozen stream, and you are responsible for deleting the array. You can unfreeze the stream by calling rdbuf->freeze( 0 ).

If the stream was built with the constructor that specified the buffer, the pointer contains the same address as the array used to construct the ostrstream object.

strstream Overview | Input/Output Stream Classes

See Also strstreambuf::freeze, strstream::rdbuf


strstream::strstream

strstream();

strstream( char* pch, int nLength, int nMode );

Parameters

pch

A character array that is large enough to accommodate future output stream activity.

nLength

The size (in characters) of pch. If 0, pch is assumed to point to a null-terminated array; if less than 0, the array is assumed to have infinite length.

nMode

The stream creation mode, which must be one of the following enumerators as defined in class ios:

  • ios::in Retrieval begins at the beginning of the array.

  • ios::out By default, storing begins at pch.

  • ios::ate The pch parameter is assumed to be a null-terminated array; storing begins at the NULL character.

  • ios::app Same as ios::ate.

    The use of the ios::in and ios::out flags is optional for this class; both input and output are implied.

Remarks

The first constructor makes an strstream object that uses an internal, dynamic buffer that is initially empty.

The second constructor makes an strstream object out of the first nLength characters of the psc buffer. The stream will not accept characters once the length reaches nLength.


strstream::~strstream

~strstream();

Remarks

Destroys a strstream object and its associated strstreambuf object, thus releasing all internally allocated memory. If you used the void-argument constructor, the internally allocated character buffer is released; otherwise, you must release it.

An internally allocated character buffer will not be released if it was previously frozen by calling rdbuf–>freeze( 0 ).

strstream Overview | Input/Output Stream Classes

See Also strstream::rdbuf


strstreambuf

#include <strstrea.h>

The strstreambuf class is a derived class of streambuf that manages an in-memory character array.

The file stream classes, ostrstream, istrstream, and strstream, use strstreambuf member functions to fetch and store characters. Some of these member functions are virtual functions defined for the streambuf class.

The reserve area, put area, and get area were introduced in the streambuf class description. For strsteambuf objects, the put area is the same as the get area, but the get pointer and the put pointer move independently.

Construction/Destruction — Public Members

strstreambuf

Constructs a strstreambuf object.

~strstreambuf

Destroys a strstreambuf object.

Other Functions — Public Members

freeze

Freezes a stream.

str

Returns a pointer to the string.

Stream Buffer Classes

See Also istrstream, ostrstream, filebuf, stdiobuf


strstreambuf::freeze

void freeze( int n = 1 );

Parameter

n

A 0 value permits automatic deletion of the current array and its automatic growth (if it is dynamic); a nonzero value prevents deletion.

Remarks

If a strstreambuf object has a dynamic array, memory is usually deleted on destruction and size adjustment. The freeze function provides a way to prevent that automatic deletion. Once an array is frozen, no further input or output is permitted. The results of such operations are undefined.

The freeze function can also unfreeze a frozen buffer.

strstreambuf Overview | Stream Buffer Classes

See Also strstreambuf::str


strstreambuf::str

char* str();

Return Value

Returns a pointer to the object’s internal character array. If the strstreambuf object was constructed with a user-supplied buffer, that buffer address is returned. If the object has a dynamic array, str freezes the array. You must not send characters to a frozen strstreambuf object, and you are responsible for deleting the array. If a dynamic array is empty, then str returns NULL.

Use the freeze function with a 0 parameter to unfreeze a strstreambuf object.

strstreambuf Overview | Stream Buffer Classes

See Also strstreambuf::freeze


strstreambuf::strstreambuf

strstreambuf();

strstreambuf( int nBytes );

strstreambuf( char* pch, int n, char* pstart = 0 );

strstreambuf( unsigned char* puch, int n, unsigned char* pustart = 0 );

strstreambuf( signed char* psch, int n, signed char* psstart = 0 );

strstreambuf( void* (*falloc)(long), void (*ffree)(void*) );

Parameters

nBytes

The initial length of a dynamic stream buffer.

pch, puch, psch

A pointer to a character buffer that will be attached to the object. The get pointer is initialized to this value.

n

One of the following integer parameters:

  • positive n bytes, starting at pch, is used as a fixed-length stream buffer.

  • 0 The pch parameter points to the start of a null-terminated string that constitutes the stream buffer (terminator excluded).

  • negative The pch parameter points to a stream buffer that continues indefinitely.

pstart, pustart, psstart

The initial value of the put pointer.

falloc

A memory-allocation function with the prototype void* falloc( long ). The default is new.

ffree

A function that frees allocated memory with the prototype void ffree( void* ). The default is delete.

Remarks

The four streambuf constructors are described as follows:

Constructor | Description
strstreambuf() | Constructs an empty strstreambuf object with dynamic buffering. The buffer is allocated internally by the class and grows as needed, unless it is frozen.
strstreambuf( int ) | Constructs an empty strstreambuf object with a dynamic buffer n bytes long to start with. The buffer is allocated internally by the class and grows as needed, unless it is frozen.
strstreambuf( char*, int, char* ) | Constructs a strstreambuf object from already-allocated memory as specified by the arguments. There are constructor variations for both unsigned and signed character arrays.
strstreambuf( void*(*), void(*) ) | Constructs an empty strstreambuf object with dynamic buffering. The falloc function is called for allocation. The long parameter specifies the buffer length and the function returns the buffer address. If the falloc pointer is NULL, operator new is used. The ffree function frees memory allocated by falloc. If the ffree pointer is NULL, the operator delete is used.


strstreambuf::~strstreambuf

~strstreambuf();

Remarks

Destroys a strstreambuf object and releases internally allocated dynamic memory unless the object is frozen. The destructor does not release user-allocated memory.


Standard C++ Library Reference

Standard C++ Library Contents
Standard C++ Library Overview
STL Conventions
Containers

Interesting home pages
Visual C++ Home The entire Visual C++ product.
MFC Reference The framework library for creating Windows programs.
Run-Time Library Reference The standard C library.


 Standard C++ Library

Standard C++ Library

A C++ program can call on a large number of functions from the Standard C++ library. These functions perform essential services such as input and output. They also provide efficient implementations of frequently used operations. Numerous function and class definitions accompany these functions to help you to make better use of the library. Most of the information about the Standard C++ library can be found in the descriptions of the Standard C++ headers that declare or define library entities for the program.


Table of Contents

<algorithm> · <bitset> · <complex> · <deque> · <exception> · <fstream> · <functional> · <iomanip> · <ios> · <iosfwd> · <iostream> · <istream> · <iterator> · <limits> · <list> · <locale> · <map> · <memory> · <numeric> · <ostream> · <queue> · <set> · <sstream> · <stack> · <stdexcept> · <streambuf> · <string> · <strstream> · <utility> · <valarray> · <vector>

<cassert> · <cctype> · <cerrno> · <cfloat> · <ciso646> · <climits> · <clocale> · <cmath> · <csetjmp> · <csignal> · <cstdarg> · <cstddef> · <cstdio> · <cstdlib> · <cstring> · <ctime> · <cwchar>

· <iso646.h> · <wchar.h>

C++ Library Overview · · Files and Streams · STL Conventions · Containers

Of the Standard C++ library headers listed below, 13 constitute the Standard Template Library, or STL. These are indicated below with the notation (STL):

<algorithm> -- (STL) for defining numerous templates that implement useful algorithms
<bitset> -- for defining a template class that administers sets of bits
<cassert> -- for enforcing assertions when functions execute
<cctype> -- for classifying characters
<cerrno> -- for testing error codes reported by library functions
<cfloat> -- for testing floating-point type properties
<ciso646> -- for programming in ISO 646 variant character sets
<climits> -- for testing integer type properties
<clocale> -- for adapting to different cultural conventions
<cmath> -- for computing common mathematical functions
<complex> -- for defining a template class that supports complex arithmetic
<csetjmp> -- for executing nonlocal goto statements
<csignal> -- for controlling various exceptional conditions
<cstdarg> -- for accessing a varying number of arguments
<cstddef> -- for defining several useful types and macros
<cstdio> -- for performing input and output
<cstdlib> -- for performing a variety of operations
<cstring> -- for manipulating several kinds of strings
<ctime> -- for converting between various time and date formats
<cwchar> -- for manipulating wide streams and several kinds of strings
<cwctype> -- for classifying wide characters
<deque> -- (STL) for defining a template class that implements a deque container
<exception> -- for defining several functions that control exception handling
<fstream> -- for defining several iostreams template classes that manipulate external files
<functional> -- (STL) for defining several templates that help construct predicates for the templates defined in <algorithm> and <numeric>
<iomanip> -- for declaring several iostreams manipulators that take an argument
<ios> -- for defining the template class that serves as the base for many iostreams classes
<iosfwd> -- for declaring several iostreams template classes before they are necessarily defined
<iostream> -- for declaring the iostreams objects that manipulate the standard streams
<istream> -- for defining the template class that performs extractions
<iterator> -- (STL) for defining several templates that help define and manipulate iterators
<limits> -- for testing numeric type properties
<list> -- (STL) for defining a template class that implements a list container
<locale> -- for defining several classes and templates that control locale-specific behavior, as in the iostreams classes
<map> -- (STL) for defining template classes that implement associative containers
<memory> -- (STL) for defining several templates that allocate and free storage for various container classes
<numeric> -- (STL) for defining several templates that implement useful numeric functions
<ostream> -- for defining the template class that performs insertions
<queue> -- (STL) for defining a template class that implements a queue container
<set> -- (STL) for defining template classes that implement associative containers with unique elements
<sstream> -- for defining several iostreams template classes that manipulate string containers
<stack> -- (STL) for defining a template class that implements a stack container
<stdexcept> -- for defining several classes useful for reporting exceptions
<streambuf> -- for defining template classes that buffer iostreams operations
<string> -- for defining a template class that implements a string container
<strstream> -- for defining several iostreams classes that manipulate in-memory character sequences
<utility> -- (STL) for defining several templates of general utility
<valarray> -- for defining several classes and template classes that support value-oriented arrays
<vector> -- (STL) for defining a template class that implements a vector container

The Standard C++ library also includes the 18 headers from the Standard C library, sometimes with small alterations. Most of the functions in the header files below are documented in the Run-Time Library Reference, so they are not discussed in this Standard C++ Library reference.

<assert.h> -- for enforcing assertions when functions execute
<ctype.h> -- for classifying characters
<errno.h> -- for testing error codes reported by library functions
<float.h> -- for testing floating-point type properties
<iso646.h> -- for programming in ISO 646 variant character sets
<limits.h> -- for testing integer type properties
<locale.h> -- for adapting to different cultural conventions
<math.h> -- for computing common mathematical functions
<setjmp.h> -- for executing nonlocal goto statements
<signal.h> -- for controlling various exceptional conditions
<stdarg.h> -- for accessing a varying number of arguments
<stddef.h> -- for defining several useful types and macros
<stdio.h> -- for performing input and output
<stdlib.h> -- for performing a variety of operations
<string.h> -- for manipulating several kinds of strings
<time.h> -- for converting between various time and date formats
<wchar.h> -- for manipulating wide streams and several kinds of strings
<wctype.h> -- for classifying wide characters

Other information on the Standard C++ library includes:

C++ Library Overview -- how to use the Standard C++ library
Files and Streams -- how to read and write data between the program and files
STL Conventions -- how to read the descriptions of STL template classes and functions
Containers -- how to use an arbitrary STL container template class

A few special conventions are introduced into this document specifically for this particular implementation of the Standard C++ library. Because the draft C++ Standard is still changing, not all implementations support all the features described here. Hence, this implementation introduces macros, or alternative declarations, where necessary to provide reasonable substitutes for the capabilities required by the current draft C++ Standard.


 C++ Library Overview

C++ Library Overview

Using Standard C++ Headers | C++ Library Conventions | Iostreams Conventions | Program Startup and Termination

All Standard C++ library entities are declared or defined in one or more standard headers. To use a library entity in a program, write an include directive that names the relevant standard header. The full set of Standard C++ headers (along with the 18 additional Standard C headers) constitutes a hosted implementation of Standard C++: <algorithm>, <bitset>, <cassert>, <cctype>, <cerrno>, <cfloat>, <ciso646>, <climits>, <clocale>, <cmath>, <complex>, <csetjmp>, <csignal>, <cstdarg>, <cstddef>, <cstdio>, <cstdlib>, <cstring>, <ctime>, <cwchar>, <cwctype>, <deque>, <exception>, <fstream>, <functional>, <iomanip>, <ios>, <iosfwd>, <iostream>, <istream>, <iterator>, <limits>, <list>, <locale>, <map>, <memory>, <numeric>, <ostream>, <queue>, <set>, <sstream>, <stack>, <stdexcept>, <streambuf>, <string>, <strstream>, <utility>, <valarray>, and <vector>.

A freestanding implementation of Standard C++ provides only a subset of these headers: <cstddef>, <cstdlib> (declaring at least the functions abort, atexit, and exit), <exception>, <limits>, and <cstdarg>.

The Standard C++ headers have two broader subdivisions, iostreams headers and STL headers.


Using Standard C++ Headers

You include the contents of a standard header by naming it in an include directive, as in:

#include <iostream>  /* include I/O facilities */

You can include the standard headers in any order, a standard header more than once, or two or more standard headers that define the same macro or the same type. Do not include a standard header within a declaration. Do not define macros that have the same names as keywords before you include a standard header.

A Standard C++ header includes any other Standard C++ headers it needs to define needed types. (Always include explicitly any Standard C++ headers needed in a translation unit, however, lest you guess wrong about its actual dependencies.) A Standard C header never includes another standard header. A standard header declares or defines only the entities described for it in this document.

Every function in the library is declared in a standard header. Unlike in Standard C, the standard header never provides a masking macro, with the same name as the function, that masks the function declaration and achieves the same effect.

If an implementation supports namespaces, all names in the Standard C++ headers are defined in the std namespace. You refer to the name cin, for example, as std::cin. Alternatively, you can write the declaration:

using namespace std;

which promotes all library names into the current namespace. If you include one of the C standard headers, such as <stdio.h>, the individual names declared or defined in that header are promoted for you. Note that macro names are not subject to the rules for nesting namespaces.


C++ Library Conventions

The Standard C++ library obeys much the same conventions as the Standard C library, plus a few more outlined here.

Except for macro names, which obey no scoping rules, all names in the Standard C++ library are declared in the std namespace. Including a Standard C++ header does not introduce any library names into the current namespace. You must, for example, refer to the standard input stream cin as std::cin, even after including the header <iostream> that declares it. Alternatively, you can incorporate all members of the std namespace into the current namespace by writing:

using namespace std;

immediately after all include directives that name the standard headers. Note that the Standard C headers behave mostly as if they include no namespace declarations. If you include, for example, <cstdlib>, you call std::abort() to cause abnormal termination, but if you include <stdlib.h>, you call abort().

An implementation has certain latitude in how it declares types and functions in the Standard C++ library:

  • Names of functions in the Standard C library may have either extern "C++" or extern "C" linkage. Include the appropriate Standard C header rather than declare a library entity inline.
  • A member function name in a library class may have additional function signatures beyond those listed in this document. You can be sure that a function call described here behaves as expected, but you cannot reliably take the address of a library member function. (The type may not be what you expect.)
  • A library class may have undocumented (nonvirtual) base classes. A class documented as derived from another class may, in fact, be derived from that class through other undocumented classes.
  • A type defined as a synonym for some integer type may be the same as one of several different integer types.
  • A library function that has no exception specification can throw an arbitrary exception, unless its definition clearly restricts such a possibility.

On the other hand, there are some restrictions you can count on:

  • The Standard C library uses no masking macros. Only specific function signatures are reserved, not the names of the functions themselves.
  • A library function name outside a class will not have additional, undocumented function signatures. You can reliably take its address.
  • Base classes and member functions described as virtual are assuredly virtual, while those described as nonvirtual are assuredly nonvirtual.
  • Two types defined by the Standard C++ library are always different unless this document explicitly suggests otherwise.
  • Functions supplied by the library, including the default versions of replaceable functions, can throw at most those exceptions listed in any exception specification. (Functions in the Standard C library may propagate an exception, as when qsort calls a comparison function that throws an exception, but they do not otherwise throw exceptions.)


Iostreams Conventions

The iostreams headers support conversions between text and encoded forms, and input and output to external files: <fstream>, <iomanip>, <ios>, <iosfwd>, <iostream>, <istream>, <ostream>, <sstream>, <streambuf>, and <strstream>.

The simplest use of iostreams requires only that you include the header <iostream>. You can then extract values from cin, to read the standard input. The rules for doing so are outlined in the description of the class basic_istream. You can also insert values to cout, to write the standard output. The rules for doing so are outlined in the description of the class basic_ostream. Format control common to both extractors and insertors is managed by the class basic_ios. Manipulating this format information in the guise of extracting and inserting objects is the province of several manipulators.

You can perform the same iostreams operations on files that you open by name, using the classes declared in <fstream>. To convert between iostreams and objects of class basic_string, use the classes declared in <sstream>. And to do the same with C strings, use the classes declared in <strstream>.

The remaining headers provide support services, typically of direct interest to only the most advanced users of the iostreams classes.


C++ Program Startup and Termination

A C++ program performs the same operations as does a C program at program startup and at program termination, plus a few more outlined here.

Before the target environment calls the function main, and after it stores any constant initial values you specify in all objects that have static duration, the program executes any remaining constructors for such static objects. The order of execution is not specified between translation units, but you can nevertheless assume that four iostreams objects are properly initialized for use by these static constructors. These control several text streams:

  • cin -- for standard input
  • cout -- for standard output
  • cerr -- for unbuffered standard error output
  • clog -- for buffered standard error output

During program termination, you can also use these objects within the destructors called for static objects.

As with C, returning from main or calling exit calls all functions registered with atexit in reverse order of registry. An exception thrown from such a registered function calls terminate ().


 STL Conventions

STL Conventions

Iterator Conventions | Algorithm Conventions

The Standard Template Library, or STL, establishes uniform standards for the application of iterators to STL containers or other sequences that you define, by STL algorithms or other functions that you define. This document summarizes many of the conventions used widely throughout the Standard Template Library.


Iterator Conventions

The STL facilities make widespread use of iterators, to mediate between the various algorithms and the sequences upon which they act. For brevity in the remainder of this document, the name of an iterator type (or its prefix) indicates the category of iterators required for that type. In order of increasing power, the categories are summarized here as:

  • OutIt -- An output iterator X can only have a value V stored indirectly on it, after which it must be incremented before the next store, as in (*X++ = V), (*X = V, ++X), or (*X = V, X++).
  • InIt -- An input iterator X can represent a singular value that indicates end-of-sequence. If such an iterator does not compare equal to its end-of-sequence value, it can have a value V accessed indirectly on it any number of times, as in (V = *X). To progress to the next value, or end-of-sequence, you increment it, as in ++X, X++, or (V = *X++). Once you increment any copy of an input iterator, none of the other copies can safely be compared, dereferenced, or incremented.
  • FwdIt -- A forward iterator X can take the place of an output iterator (for writing) or an input iterator (for reading). You can, however, read (via V = *X) what you just wrote (via *X = V) through a forward iterator. And you can make multiple copies of a forward iterator, each of which can be dereferenced and incremented independently.
  • BidIt -- A bidirectional iterator X can take the place of a forward iterator. You can, however, also decrement a bidirectional iterator, as in --X, X--, or (V = *X--).
  • RanIt -- A random-access iterator X can take the place of a bidirectional iterator. You can also perform much the same integer arithmetic on a random-access iterator that you can on an object pointer. For N, an integer object, you can write x[N], x + N, x - N, and N + X.

Note that an object pointer can take the place of a random-access iterator, or any other iterator for that matter.

The hierarchy of iterator categories can be summarized by showing three sequences. For write-only access to a sequence, you can use any of:

output iterator ->
    forward iterator ->
    bidirectional iterator ->
    random-access iterator

The right arrow means "can be replaced by." So any algorithm that calls for an output iterator should work well with a forward iterator, for example, but not the other way around.

For read-only access to a sequence, you can use any of:

input iterator ->
    forward iterator ->
    bidirectional iterator ->
    random-access iterator

An input iterator is the weakest of all categories, in this case.

Finally, for read/write access to a sequence, you can use any of:

forward iterator ->
    bidirectional iterator ->
    random-access iterator

Remember that an object pointer can always serve as a random-access iterator. Therefore, it can serve as any category of iterator, as long as it supports the proper read/write access to the sequence it designates.

This "algebra" of iterators is fundamental to practically everything else in the Standard Template Library. It is important to understand the capabilities, and limitations, of each iterator category to see how iterators are used by containers and algorithms in STL.


Algorithm Conventions

The descriptions of the algorithm template functions employ several shorthand phrases:

  • The phrase "in the range [A, B)" means the sequence of zero or more discrete values beginning with A up to but not including B. A range is valid only if B is reachable from A: You can store A in an object N (N = A), increment the object zero or more times (++N), and have the object compare equal to B after a finite number of increments (N == B).
  • The phrase "each N in the range [A, B)" means that N begins with the value A and is incremented zero or more times until it equals the value B. The case N == B is not in the range.
  • The phrase "the lowest value of N in the range [A, B) such that X" means that the condition X is determined for each N in the range [A, B) until the condition X is met.
  • The phrase "the highest value of N in the range [A, B) such that X" usually means that X is determined for each N in the range [A, B). The function stores in K a copy of N each time the condition X is met. If any such store occurs, the function replaces the final value of N (which equals B) with the value of K. For a bidirectional or random-access iterator, however, it can also mean that N begins with the highest value in the range and is decremented over the range until the condition X is met.
  • Expressions such as X - Y, where X and Y can be iterators other than random-access iterators, are intended in the mathematical sense. The function does not necessarily evaluate operator- if it must determine such a value. The same is true for expressions such as X + N and X - N, where N is an integer type.

Several algorithms use a predicate that must impose a strict weak ordering on pairs of elements from a sequence. For the predicate pr(X, Y):

  • "strict" means that pr(X, X) is false
  • "weak" means that X and Y have an equivalent ordering if !pr(X, Y) && !pr(Y, X) (X == Y need not be defined)
  • "ordering" means that pr(X, Y) && pr(Y, Z) implies pr(X, Z)

Some of these algorithms implicitly use the predicate X < Y. Other predicates that typically satisfy the "strict weak ordering" requirement are X > Y, less (X, Y), and greater (X, Y). Note, however, that predicates such as X <= Y and X >= Y do not satisfy this requirement.

A sequence of elements designated by iterators in the range [first, last) is "a sequence ordered by operator<" if, for each N in the range [0, last - first) and for each M in the range (N, last - first) the predicate !(*(first + M) < *(first + N)) is true. (Note that the elements are sorted in ascending order.) The predicate function operator<, or any replacement for it, must not alter either of its operands. Moreover, it must impose a strict weak ordering on the operands it compares.

A sequence of elements designated by iterators in the range [first, last) is "a heap ordered by operator<" if, for each N in the range [1, last - first) the predicate !(*first < *(first + N)) is true. (The first element is the largest.) Its internal structure is otherwise known only to the template functions make_heap, pop_heap, and push_heap. As with an ordered sequence, the predicate function operator<, or any replacement for it, must not alter either of its operands, and it must impose a strict weak ordering on the operands it compares.


 Files and Streams

Files and Streams

Text and Binary Streams | Byte and Wide Streams | Controlling Streams | Stream States

A program communicates with the target environment by reading and writing files (ordered sequences of bytes). A file can be, for example, a data set that you can read and write repeatedly (such as a disk file), a stream of bytes generated by a program (such as a pipeline), or a stream of bytes received from or sent to a peripheral device (such as the keyboard or display). The latter two are interactive files. Files are typically the principal means by which to interact with a program.

You manipulate all these kinds of files in much the same way -- by calling library functions. You include the standard header <stdio.h> to declare most of these functions.

Before you can perform many of the operations on a file, the file must be opened. Opening a file associates it with a stream, a data structure within the Standard C library that glosses over many differences among files of various kinds. The library maintains the state of each stream in an object of type FILE.

The target environment opens three files prior to program startup. You can open a file by calling the library function fopen with two arguments. The first argument is a filename, a multibyte string that the target environment uses to identify which file you want to read or write. The second argument is a C string that specifies:

  • Whether you intend to read data from the file or write data to it, or both.
  • Whether you intend to generate new contents for the file (or create a file if it did not previously exist) or leave the existing contents in place.
  • Whether writes to a file can alter existing contents or should only append bytes at the end of the file.
  • Whether you want to manipulate a text stream or a binary stream.

Once the file is successfully opened, you can determine whether the stream is byte-oriented (a byte stream) or wide-oriented (a wide stream). Wide-oriented streams are supported only with Amendment 1. A stream is initially unbound. Calling certain functions to operate on the stream makes it byte oriented, while certain other functions make it wide oriented. Once established, a stream maintains its orientation until it is closed by a call to fclose or freopen.


Text and Binary Streams

A text stream consists of one or more lines of text that can be written to a text-oriented display so that they can be read. When reading from a text stream, the program reads an NL (newline) at the end of each line. When writing to a text stream, the program writes an NL to signal the end of a line. To match differing conventions among target environments for representing text in files, the library functions can alter the number and representations of characters transmitted between the program and a text stream.

Thus, positioning within a text stream is limited. You can obtain the current file-position indicator by calling fgetpos or ftell. You can place a text stream at a position obtained this way, or at the beginning or end of the stream, by calling fsetpos or fseek. Any other change of position might well be unsupported.

For maximum portability, the program should not write:

  • Empty files
  • Space characters at the end of a line
  • Partial lines (by omitting the NL at the end of a file)
  • Characters other than the printable characters, NL, and HT (horizontal tab)

If you follow these rules, the sequence of characters you read from a text stream (either as byte or multibyte characters) will match the sequence of characters you wrote to the text stream when you created the file. Otherwise, the library functions can remove a file you create if the file is empty when you close it. Or they can alter or delete characters you write to the file.

A binary stream consists of one or more bytes of arbitrary information. You can write the value stored in an arbitrary object to a (byte-oriented) binary stream and read exactly what was stored in the object when you wrote it. The library functions do not alter the bytes you transmit between the program and a binary stream. They can, however, append an arbitrary number of null bytes to the file that you write with a binary stream. The program must deal with these additional null bytes at the end of any binary stream.

Thus, positioning within a binary stream is well defined, except for positioning relative to the end of the stream. You can obtain and alter the current file-position indicator the same as for a text stream. Moreover, the offsets used by ftell and fseek count bytes from the beginning of the stream (which is byte zero), so integer arithmetic on these offsets yields predictable results.


Byte and Wide Streams

A byte stream treats a file as a sequence of bytes. Within the program, the stream looks like the same sequence of bytes, except for the possible alterations described above.

By contrast, a wide stream treats a file as a sequence of generalized multibyte characters, which can have a broad range of encoding rules. (Text and binary files are still read and written as described above.) Within the program, the stream looks like the corresponding sequence of wide characters. Conversions between the two representations occur within the Standard C library. The conversion rules can, in principle, be altered by a call to setlocale that changes the category LC_CTYPE. Each wide stream determines its conversion rules at the time it becomes wide-oriented, and retains these rules even if the category LC_CTYPE subsequently changes.

Positioning within a wide stream is subject to the same limitations as for text streams. Moreover, the file-position indicator may well have to deal with a state-dependent encoding. Typically, it includes both a byte offset within the stream and an object of type mbstate_t. Thus, the only reliable way to obtain a file position within a wide stream is by calling fgetpos, and the only reliable way to restore a position obtained this way is by calling fsetpos.


Controlling Streams

The fopen function returns the address of an object of type FILE. You use this address as the stream argument to several library functions to perform various operations on an open file. For a byte stream, all input takes place as if each character is read by calling fgetc, and all output takes place as if each character is written by calling fputc. For a wide stream (with Amendment 1), all input takes place as if each character is read by calling fgetwc, and all output takes place as if each character is written by calling fputwc.

You can close a file by calling fclose, after which the address of the FILE object is invalid.

A FILE object stores the state of a stream, including:

  • An error indicator -- set nonzero by a function that encounters a read or write error
  • An end-of-file indicator -- set nonzero by a function that encounters the end of the file while reading
  • A file-position indicator -- specifies the next byte in the stream to read or write, if the file can support positioning requests
  • A stream state -- specifies whether the stream will accept reads and/or writes and, with Amendment 1, whether the stream is unbound, byte-oriented, or wide-oriented
  • A conversion state -- remembers the state of any partly assembled or generated generalized multibyte character, as well as any shift state for the sequence of bytes in the file
  • A file buffer -- specifies the address and size of an array object that library functions can use to improve the performance of read and write operations to the stream

Do not alter any value stored in a FILE object or in a file buffer that you specify for use with that object. You cannot copy a FILE object and portably use the address of the copy as a stream argument to a library function.


Stream States

The valid states, and state transitions, for a stream are:

Each of the circles denotes a stable state. Each of the lines denotes a transition that can occur as the result of a function call that operates on the stream. Five groups of functions can cause state transitions.

Functions in the first three groups are declared in <stdio.h>:

  • The byte read functions -- fgetc, fgets, fread, fscanf, getc, getchar, gets, scanf, and ungetc
  • The byte write functions -- fprintf, fputc, fputs, fwrite, printf, putc, putchar, puts, vfprintf, and vprintf
  • The position functions -- fflush, fseek, fsetpos, and rewind

Functions in the remaining two groups are declared in <wchar.h>:

  • The wide read functions -- fgetwc, fgetws, fwscanf, getwc, getwchar, ungetwc, and wscanf,
  • The wide write functions -- fwprintf, fputwc, fputws, putwc, putwchar, vfwprintf, vwprintf, and wprintf

For the stream s, the call fwide (s, 0) is always valid and never causes a change of state. Any other call to fwide, or to any of the five groups of functions described above, causes the state transition shown in the state diagram. If no such transition is shown, the function call is invalid.

The state diagram shows how to establish the orientation of a stream:

  • The call fwide (s, -1), or to a byte read or byte write function, establishes the stream as byte-oriented.
  • The call fwide (s, 1), or to a wide read or wide write function, establishes the stream as wide-oriented.

The state diagram also shows that you must call one of the position functions between most write and read operations:

  • You cannot call a read function if the last operation on the stream was a write.
  • You cannot call a write function if the last operation on the stream was a read, unless that read operation set the end-of-file indicator.

Finally, the state diagram shows that a position operation never decreases the number of valid function calls that can follow.


 Containers

Containers

namespace std {
template<class T, class A>
    class Cont;
//    TEMPLATE FUNCTIONS
template<class T, class A>
    bool operator==(
        const Cont<T, A>& lhs,
        const Cont<T, A>& rhs);
template<class T, class A>
    bool operator!=(
        const Cont<T, A>& lhs,
        const Cont<T, A>& rhs);
template<class T, class A>
    bool operator<(
        const Cont<T, A>& lhs,
        const Cont<T, A>& rhs);
template<class T, class A>
    bool operator>(
        const Cont<T, A>& lhs,
        const Cont<T, A>& rhs);
template<class T, class A>
    bool operator<=(
        const Cont<T, A>& lhs,
        const Cont<T, A>& rhs);
template<class T, class A>
    bool operator>=(
        const Cont<T, A>& lhs,
        const Cont<T, A>& rhs);
template<class T, class A>
    void swap(
        const Cont<T, A>& lhs,
        const Cont<T, A>& rhs);
    };

A container is an STL template class that manages a sequence of elements. Such elements can be of any object type that supplies a default constructor, a destructor, and an assignment operator. This document describes the properties required of all such containers, in terms of a generic template class Cont. An actual container template class may have additional template parameters. It will certainly have additional member functions.

The STL template container classes are:

    deque
    list
    map
    multimap
    multiset
    set
    vector

(The Standard C++ library template class basic_string also meets the requirements for a template container class.)


Cont

allocator_type · begin · clear · const_iterator · const_reference · const_reverse_iterator · difference_type · empty · end · erase · get_allocator · iterator · max_size · rbegin · reference · rend · reverse_iterator · size · size_type · swap · value_type

template<class T, class A = allocator<T> >
    class Cont {
public:
    typedef A allocator_type;
    typedef T0 size_type;
    typedef T1 difference_type;
    typedef T2 reference;
    typedef T3 const_reference;
    typedef T4 value_type;
    typedef T5 iterator;
    typedef T6 const_iterator;
    typedef T7 reverse_iterator;
    typedef T8 const_reverse_iterator;
    iterator begin();
    const_iterator begin() const;
    iterator end();
    const_iterator end() const;
    reverse_iterator rbegin();
    const_reverse_iterator rbegin() const;
    reverse_iterator rend();
    const_reverse_iterator rend() const;
    size_type size() const;
    size_type max_size() const;
    bool empty() const;
    A get_allocator() const;
    iterator erase(iterator it);
    iterator erase(iterator first, iterator last);
    void clear();
    void swap(Cont x);
protected:
    A allocator;
    };

The template class describes an object that controls a varying-length sequence of elements, typically of type T. The sequence is stored in different ways, depending on the actual container.

The object allocates and frees storage for the sequence it controls through a protected object named allocator, of class A. Such an allocator object must have the same external interface as an object of template class allocator. Note that allocator is not copied when the object is assigned. All constructors store an allocator argument (or, for the copy constructor, x. get_allocator ()) in allocator and initialize the controlled sequence.


Cont::allocator_type

typedef A allocator_type;

The type is a synonym for the template parameter A.


Cont::begin

const_iterator begin() const;
iterator begin();

The member function returns an iterator that points at the first element of the sequence (or just beyond the end of an empty sequence).


Cont::clear

void clear() const;

The member function calls erase ( begin (), end ()).


Cont::const_iterator

typedef T6 const_iterator;

The type describes an object that can serve as a constant iterator for the controlled sequence. It is described here as a synonym for the unspecified type T6.


Cont::const_reference

typedef T3 const_reference;

The type describes an object that can serve as a constant reference to an element of the controlled sequence. It is described here as a synonym for the unspecified type T3 (typically A::const_reference).


Cont::const_reverse_iterator

typedef T8 const_reverse_iterator;

The type describes an object that can serve as a constant reverse iterator for the controlled sequence. It is described here as a synonym for the unspecified type T8 (typically reverse_iterator or reverse_bidirectional_iterator).


Cont::difference_type

typedef T1 difference_type;

The signed integer type describes an object that can represent the difference between the addresses of any two elements in the controlled sequence. It is described here as a synonym for the unspecified type T1 (typically A::difference_type).


Cont::empty

bool empty() const;

The member function returns true for an empty controlled sequence.


Cont::end

const_iterator end() const;
iterator end();

The member function returns an iterator that points just beyond the end of the sequence.


Cont::erase

iterator erase(iterator it);
iterator erase(iterator first, iterator last);

The first member function removes the element of the controlled sequence pointed to by it. The second member function removes the elements of the controlled sequence in the range [first, last). Both return an iterator that designates the first element remaining beyond any elements removed, or end () if no such element exists.


Cont::get_allocator

A get_allocator() const;

The member function returns allocator.


Cont::iterator

typedef T5 iterator;

The type describes an object that can serve as an iterator for the controlled sequence. It is described here as a synonym for the unspecified type T5.


Cont::max_size

size_type max_size() const;

The member function returns the length of the longest sequence that the object can control.


Cont::rbegin

const_reverse_iterator rbegin() const;
reverse_iterator rbegin();

The member function returns a reverse iterator that points just beyond the end of the controlled sequence. Hence, it designates the beginning of the reverse sequence.


Cont::reference

typedef T2 reference;

The type describes an object that can serve as a reference to an element of the controlled sequence. It is described here as a synonym for the unspecified type T2 (typically A::reference).


Cont::rend

const_reverse_iterator rend() const;
reverse_iterator rend();

The member function returns a reverse iterator that points at the first element of the sequence (or just beyond the end of an empty sequence). Hence, it designates the end of the reverse sequence.


Cont::reverse_iterator

typedef T7 reverse_iterator;

The type describes an object that can serve as a reverse iterator for the controlled sequence. It is described here as a synonym for the unspecified type T7 (typically reverse_iterator or reverse_bidirectional_iterator).

The required pointer type is described here as the unspecified type T7 (typically A::pointer).


Cont::size

size_type size() const;

The member function returns the length of the controlled sequence.


Cont::size_type

typedef T0 size_type;

The unsigned integer type describes an object that can represent the length of any controlled sequence. It is described here as a synonym for the unspecified type T0 (typically A::size_type).


Cont::swap

void swap(Cont& str);

The member function swaps the controlled sequences between *this and str. If allocator == str.allocator, it does so in constant time. Otherwise, it performs a number of element assignments and constructor calls proportional to the number of elements in the two controlled sequences.


Cont::value_type

typedef T4 value_type;

The type is a synonym for the template parameter T. It is described here as a synonym for the unspecified type T4 (typically A::value_type).


operator!=

template<class T, class A>
    bool operator!=(
        const Cont <T, A>& lhs,
        const Cont <T, A>& rhs);

The template function returns !(lhs == rhs).


operator==

template<class T, class A>
    bool operator==(
        const Cont <T, A>& lhs,
        const Cont <T, A>& rhs);

The template function overloads operator== to compare two objects of template class Cont. The function returns lhs. size () == rhs.size() && equal (lhs. begin (), lhs. end (), rhs.begin()).


operator<

template<class T, class A>
    bool operator<(
        const Cont <T, A>& lhs,
        const Cont <T, A>& rhs);

The template function overloads operator< to compare two objects of template class Cont. The function returns lexicographical_compare (lhs. begin (), lhs. end (), rhs.begin(), rhs.end()).


operator<=

template<class T, class A>
    bool operator<=(
        const Cont <T, A>& lhs,
        const Cont <T, A>& rhs);

The template function returns !(rhs < lhs).


operator>

template<class T, class A>
    bool operator>(
        const Cont <T, A>& lhs,
        const Cont <T, A>& rhs);

The template function returns rhs < lhs.


operator>=

template<class T, class A>
    bool operator>=(
        const Cont <T, A>& lhs,
        const Cont <T, A>& rhs);

The template function returns !(lhs < rhs).


swap

template<class T, class A>
    void swap(
        const Cont <T, A>& lhs,
        const Cont <T, A>& rhs);

The template function executes lhs. swap (rhs).


 <algorithm>

<algorithm>

adjacent_find · binary_search · copy · copy_backward · count · count_if · equal · equal_range · fill · fill_n · find · find_end · find_first_of · find_if · for_each · generate · generate_n · includes · inplace_merge · iter_swap · lexicographical_compare · lower_bound · make_heap · max · max_element · merge · min · min_element · mismatch · next_permutation · nth_element · partial_sort · partial_sort_copy · partition · pop_heap · prev_permutation · push_heap · random_shuffle · remove · remove_copy · remove_copy_if · remove_if · replace · replace_copy · replace_copy_if · replace_if · reverse · reverse_copy · rotate · rotate_copy · search · search_n · ; set_difference · set_intersection · set_symmetric_difference · set_union · sort · sort_heap · stable_partition · stable_sort · swap · swap_ranges · transform · unique · unique_copy · upper_bound

namespace std {
template<class InIt, class Fun>
    Fun for_each(InIt first, InIt last, Fun f);
template<class InIt, class T>
    InIt find(InIt first, InIt last, const T& val);
template<class InIt, class Pred>
    InIt find_if(InIt first, InIt last, Pred pr);
template<class FwdIt1, class FwdIt2>
    FwdIt1 find_end(FwdIt1 first1, FwdIt1 last1,
        FwdIt2 first2, FwdIt2 last2);
template<class FwdIt1, class FwdIt2, class Pred>
    FwdIt1 find_end(FwdIt1 first1, FwdIt1 last1,
        FwdIt2 first2, FwdIt2 last2, Pred pr);
template<class FwdIt1, class FwdIt2>
    FwdIt1 find_first_of(FwdIt1 first1, FwdIt1 last1,
        FwdIt2 first2, FwdIt2 last2);
template<class FwdIt1, class FwdIt2, class Pred>
    FwdIt1 find_first_of(FwdIt1 first1, FwdIt1 last1,
        FwdIt2 first2, FwdIt2 last2, Pred pr);
template<class FwdIt>
    FwdIt adjacent_find(FwdIt first, FwdIt last);
template<class FwdIt, class Pred>
    FwdIt adjacent_find(FwdIt first, FwdIt last, Pred pr);
    size_t count(InIt first, InIt last,
        const T& val, Dist& n);
template<class InIt, class Pred, class Dist>
    size_t count_if(InIt first, InIt last,
        Pred pr);
template<class InIt1, class InIt2>
    pair<InIt1, InIt2> mismatch(InIt1 first, InIt1 last, InIt2 x);
template<class InIt1, class InIt2, class Pred>
    pair<InIt1, InIt2> mismatch(InIt1 first, InIt1 last,
        InIt2 x, Pred pr);
template<class InIt1, class InIt2>
    bool equal(InIt1 first, InIt1 last, InIt2 x);
template<class InIt1, class InIt2, class Pred>
    bool equal(InIt1 first, InIt1 last, InIt2 x, Pred pr);
template<class FwdIt1, class FwdIt2>
    FwdIt1 search(FwdIt1 first1, FwdIt1 last1,
        FwdIt2 first2, FwdIt2 last2);
template<class FwdIt1, class FwdIt2, class Pred>
    FwdIt1 search(FwdIt1 first1, FwdIt1 last1,
        FwdIt2 first2, FwdIt2 last2, Pred pr);
template<class FwdIt, class Dist, class T>
    FwdIt search_n(FwdIt first, FwdIt last,
        Dist n, const T& val);
template<class FwdIt, class Dist, class T, class Pred>
    FwdIt search_n(FwdIt first, FwdIt last,
        Dist n, const T& val, Pred pr);
template<class InIt, class OutIt>
    OutIt copy(InIt first, InIt last, OutIt x);
template<class BidIt1, class BidIt2>
    BidIt2 copy_backward(BidIt1 first, BidIt1 last, BidIt2 x);
template<class T>
    void swap(T& x, T& y);
template<class FwdIt1, class FwdIt2>
    FwdIt2 swap_ranges(FwdIt1 first, FwdIt1 last, FwdIt2 x);
template<class FwdIt1, class FwdIt2>
    void iter_swap(FwdIt1 x, FwdIt2 y);
template<class InIt, class OutIt, class Unop>
    OutIt transform(InIt first, InIt last, OutIt x, Unop uop);
template<class InIt1, class InIt2, class OutIt, class Binop>
    OutIt transform(InIt1 first1, InIt1 last1, InIt2 first2,
        OutIt x, Binop bop);
template<class FwdIt, class T>
    void replace(FwdIt first, FwdIt last,
        const T& vold, const T& vnew);
template<class FwdIt, class Pred, class T>
    void replace_if(FwdIt first, FwdIt last,
        Pred pr, const T& val);
template<class InIt, class OutIt, class T>
    OutIt replace_copy(InIt first, InIt last, OutIt x,
        const T& vold, const T& vnew);
template<class InIt, class OutIt, class Pred, class T>
    OutIt replace_copy_if(InIt first, InIt last, OutIt x,
        Pred pr, const T& val);
template<class FwdIt, class T>
    void fill(FwdIt first, FwdIt last, const T& x);
template<class OutIt, class Size, class T>
    void fill_n(OutIt first, Size n, const T& x);
template<class FwdIt, class Gen>
    void generate(FwdIt first, FwdIt last, Gen g);
template<class OutIt, class Pred, class Gen>
    void generate_n(OutIt first, Dist n, Gen g);
template<class FwdIt, class T>
    FwdIt remove(FwdIt first, FwdIt last, const T& val);
template<class FwdIt, class Pred>
    FwdIt remove_if(FwdIt first, FwdIt last, Pred pr);
template<class InIt, class OutIt, class T>
    OutIt remove_copy(InIt first, InIt last, OutIt x, const T& val);
template<class InIt, class OutIt, class Pred>
    OutIt remove_copy_if(InIt first, InIt last, OutIt x, Pred pr);
template<class FwdIt>
    FwdIt unique(FwdIt first, FwdIt last);
template<class FwdIt, class Pred>
    FwdIt unique(FwdIt first, FwdIt last, Pred pr);
template<class InIt, class OutIt>
    OutIt unique_copy(InIt first, InIt last, OutIt x);
template<class InIt, class OutIt, class Pred>
    OutIt unique_copy(InIt first, InIt last, OutIt x, Pred pr);
template<class BidIt>
    void reverse(BidIt first, BidIt last);
template<class BidIt, class OutIt>
    OutIt reverse_copy(BidIt first, BidIt last, OutIt x);
template<class FwdIt>
    void rotate(FwdIt first, FwdIt middle, FwdIt last);
template<class FwdIt, class OutIt>
    OutIt rotate_copy(FwdIt first, FwdIt middle, FwdIt last, OutIt x);
template<class RanIt>
    void random_shuffle(RanIt first, RanIt last);
template<class RanIt, class Fun>
    void random_shuffle(RanIt first, RanIt last, Fun& f);
template<class BidIt, class Pred>
    BidIt partition(BidIt first, BidIt last, Pred pr);
template<class FwdIt, class Pred>
    FwdIt stable_partition(FwdIt first, FwdIt last, Pred pr);
template<class RanIt>
    void sort(RanIt first, RanIt last);
template<class RanIt, class Pred>
    void sort(RanIt first, RanIt last, Pred pr);
template<class BidIt>
    void stable_sort(BidIt first, BidIt last);
template<class BidIt, class Pred>
    void stable_sort(BidIt first, BidIt last, Pred pr);
template<class RanIt>
    void partial_sort(RanIt first, RanIt middle, RanIt last);
template<class RanIt, class Pred>
    void partial_sort(RanIt first, RanIt middle, RanIt last, Pred pr);
template<class InIt, class RanIt>
    RanIt partial_sort_copy(InIt first1, InIt last1,
        RanIt first2, RanIt last2);
template<class InIt, class RanIt, class Pred>
    RanIt partial_sort_copy(InIt first1, InIt last1,
        RanIt first2, RanIt last2, Pred pr);
template<class RanIt>
    void nth_element(RanIt first, RanIt nth, RanIt last);
template<class RanIt, class Pred>
    void nth_element(RanIt first, RanIt nth, RanIt last, Pred pr);
template<class FwdIt, class T>
    FwdIt lower_bound(FwdIt first, FwdIt last, const T& val);
template<class FwdIt, class T, class Pred>
    FwdIt lower_bound(FwdIt first, FwdIt last, const T& val, Pred pr);
template<class FwdIt, class T>
    FwdIt upper_bound(FwdIt first, FwdIt last, const T& val);
template<class FwdIt, class T, class Pred>
    FwdIt upper_bound(FwdIt first, FwdIt last, const T& val, Pred pr);
template<class FwdIt, class T>
    pair<FwdIt, FwdIt> equal_range(FwdIt first, FwdIt last,
        const T& val);
template<class FwdIt, class T, class Pred>
    pair<FwdIt, FwdIt> equal_range(FwdIt first, FwdIt last,
        const T& val, Pred pr);
template<class FwdIt, class T>
    bool binary_search(FwdIt first, FwdIt last, const T& val);
template<class FwdIt, class T, class Pred>
    bool binary_search(FwdIt first, FwdIt last, const T& val,
        Pred pr);
template<class InIt1, class InIt2, class OutIt>
    OutIt merge(InIt1 first1, InIt1 last1,
        InIt2 first2, InIt2 last2, OutIt x);
template<class InIt1, class InIt2, class OutIt, class Pred>
    OutIt merge(InIt1 first1, InIt1 last1,
        InIt2 first2, InIt2 last2, OutIt x, Pred pr);
template<class BidIt>
    void inplace_merge(BidIt first, BidIt middle, BidIt last);
template<class BidIt, class Pred>
    void inplace_merge(BidIt first, BidIt middle, BidIt last, Pred pr);
template<class InIt1, class InIt2>
    bool includes(InIt1 first1, InIt1 last1,
        InIt2 first2, InIt2 last2);
template<class InIt1, class InIt2, class Pred>
    bool includes(InIt1 first1, InIt1 last1,
        InIt2 first2, InIt2 last2, Pred pr);
template<class InIt1, class InIt2, class OutIt>
    OutIt set_union(InIt1 first1, InIt1 last1,
        InIt2 first2, InIt2 last2, OutIt x);
template<class InIt1, class InIt2, class OutIt, class Pred>
    OutIt set_union(InIt1 first1, InIt1 last1,
        InIt2 first2, InIt2 last2, OutIt x, Pred pr);
template<class InIt1, class InIt2, class OutIt>
    OutIt set_intersection(InIt1 first1, InIt1 last1,
        InIt2 first2, InIt2 last2, OutIt x);
template<class InIt1, class InIt2, class OutIt, class Pred>
    OutIt set_intersection(InIt1 first1, InIt1 last1,
        InIt2 first2, InIt2 last2, OutIt x, Pred pr);
template<class InIt1, class InIt2, class OutIt>
    OutIt set_difference(InIt1 first1, InIt1 last1,
        InIt2 first2, InIt2 last2, OutIt x);
template<class InIt1, class InIt2, class OutIt, class Pred>
    OutIt set_difference(InIt1 first1, InIt1 last1,
        InIt2 first2, InIt2 last2, OutIt x, Pred pr);
template<class InIt1, class InIt2, class OutIt>
    OutIt set_symmetric_difference(InIt1 first1, InIt1 last1,
        InIt2 first2, InIt2 last2, OutIt x);
template<class InIt1, class InIt2, class OutIt, class Pred>
    OutIt set_symmetric_difference(InIt1 first1, InIt1 last1,
        InIt2 first2, InIt2 last2, OutIt x, Pred pr);
template<class RanIt>
    void push_heap(RanIt first, RanIt last);
template<class RanIt, class Pred>
    void push_heap(RanIt first, RanIt last, Pred pr);
template<class RanIt>
    void pop_heap(RanIt first, RanIt last);
template<class RanIt, class Pred>
    void pop_heap(RanIt first, RanIt last, Pred pr);
template<class RanIt>
    void make_heap(RanIt first, RanIt last);
template<class RanIt, class Pred>
    void make_heap(RanIt first, RanIt last, Pred pr);
template<class RanIt>
    void sort_heap(RanIt first, RanIt last);
template<class RanIt, class Pred>
    void sort_heap(RanIt first, RanIt last, Pred pr);
template<class T>
    const T& max(const T& x, const T& y);
template<class T, class Pred>
    const T& max(const T&  x, const T& y, Pred pr);
template<class T>
    const T& min(const T& x, const T& y);
template<class T, class Pred>
    const T& min(const T& x, const T& y, Pred pr);
template<class FwdIt>
    FwdIt max_element(FwdIt first, FwdIt last);
template<class FwdIt, class Pred>
    FwdIt max_element(FwdIt first, FwdIt last, Pred pr);
template<class FwdIt>
    FwdIt min_element(FwdIt first, FwdIt last);
template<class FwdIt, class Pred>
    FwdIt min_element(FwdIt first, FwdIt last, Pred pr);
template<class InIt1, class InIt2>
    bool lexicographical_compare(InIt1 first1, InIt1 last1,
        InIt2 first2, InIt2 last2);
template<class InIt1, class InIt2, class Pred>
    bool lexicographical_compare(InIt1 first1, InIt1 last1,
        InIt2 first2, InIt2 last2, Pred pr);
template<class BidIt>
    bool next_permutation(BidIt first, BidIt last);
template<class BidIt, class Pred>
    bool next_permutation(BidIt first, BidIt last, Pred pr);
template<class BidIt>
    bool prev_permutation(BidIt first, BidIt last);
template<class BidIt, class Pred>
    bool prev_permutation(BidIt first, BidIt last, Pred pr);
    };

Include the STL standard header <algorithm> to define numerous template functions that perform useful algorithms. The descriptions that follow make extensive use of common template parameter names (or prefixes) to indicate the least powerful category of iterator permitted as an actual argument type:

  • OutIt -- to indicate an output iterator
  • InIt -- to indicate an input iterator
  • FwdIt -- to indicate a forward iterator
  • BidIt -- to indicate a bidirectional iterator
  • RanIt -- to indicate a random-access iterator

The descriptions of these templates employ a number of conventions common to all algorithms.


adjacent_find

template<class FwdIt>
    FwdIt adjacent_find(FwdIt first, FwdIt last);
template<class FwdIt, class Pred>
    FwdIt adjacent_find(FwdIt first, FwdIt last, Pred pr);

The first template function determines the lowest N in the range [0, last - first) for which N + 1 != last - first and the predicate *(first + N) == *(first + N + 1) is true. It then returns first + N. If no such value exists, the function returns last. It evaluates the predicate exactly N + 1 times.

The second template function behaves the same, except that the predicate is pr(*(first + N), *(first + N + 1)).

Sample programs: adjacent_find and adjacent_find (predicate version).


binary_search

template<class FwdIt, class T>
    bool binary_search(FwdIt first, FwdIt last, const T& val);
template<class FwdIt, class T, class Pred>
    bool binary_search(FwdIt first, FwdIt last, const T& val,
        Pred pr);

The first template function determines whether a value of N exists in the range [0, last - first) for which *(first + N) has equivalent ordering to val, where the elements designated by iterators in the range [first, last) form a sequence ordered by operator<. If so, the function returns true. If no such value exists, it returns false.

If FwdIt is a random-access iterator type, the function evaluates the ordering predicate X < Y at most ceil(log(last - first)) + 2 times. Otherwise, the function evaluates the predicate a number of times proportional to last - first.

The second template function behaves the same, except that it replaces operator<(X, Y) with pr(X, Y).


copy

template<class InIt, class OutIt>
    OutIt copy(InIt first, InIt last, OutIt x);

The template function evaluates *(x + N) = *(first + N)) once for each N in the range [0, last - first), for strictly increasing values of N beginning with the lowest value. It then returns x + N. If x and first designate regions of storage, x must not be in the range [first, last).


copy_backward

template<class BidIt1, class BidIt2>
    BidIt2 copy_backward(BidIt1 first, BidIt1 last, BidIt2 x);

The template function evaluates *(x - N - 1) = *(last - N - 1)) once for each N in the range [0, last - first), for strictly decreasing values of N beginning with the highest value. It then returns x - (last - first). If x and first designate regions of storage, x must not be in the range [first, last).


count

template<class InIt, class T>
    size_t count(InIt first, InIt last,
        const T& val);

The template function sets a count n to zero. It then executes ++n for each N in the range [0, last - first) for which the predicate *(first + N) == val is true. The function returns n. It evaluates the predicate exactly last - first times.

In this implementation, if a translator does not support partial specialization of templates, the return type is size_t instead of iterator_traits<InIt>::distance_type.

See the related sample program.


count_if

template<class InIt, class Pred, class Dist>
    size_t count_if(InIt first, InIt last,
        Pred pr);

The template function sets a count n to zero. It then executes ++n for each N in the range [0, last - first) for which the predicate pr(*(first + N)) is true. It evaluates the predicate exactly last - first times.

In this implementation, if a translator does not support partial specialization of templates, the return type is size_t instead of iterator_traits<InIt>::distance_type.

See the related sample program.


equal

template<class InIt1, class InIt2>
    bool equal(InIt1 first, InIt1 last, InIt2 x);
template<class InIt1, class InIt2, class Pred>
    bool equal(InIt1 first, InIt1 last, InIt2 x, Pred pr);

The first template function returns true only if, for each N in the range [0, last1 - first1), the predicate *(first1 + N) == *(first2 + N) is true. The function evaluates the predicate once, at most, for each N.

The second template function behaves the same, except that the predicate is pr(*(first1 + N), *(first2 + N)).


equal_range

template<class FwdIt, class T>
    pair<FwdIt, FwdIt> equal_range(FwdIt first, FwdIt last,
        const T& val);
template<class FwdIt, class T, class Pred>
    pair<FwdIt, FwdIt> equal_range(FwdIt first, FwdIt last,
        const T& val, Pred pr);

The first template function effectively returns pair ( lower_bound (first, last, val), upper_bound (first, last, val)), where the elements designated by iterators in the range [first, last) form a sequence ordered by operator<. Thus, the function determines the largest range of positions over which val can be inserted in the sequence and still preserve its ordering.

If FwdIt is a random-access iterator type, the function evaluates the ordering predicate X < Y at most ceil(2 * log(last - first)) + 1 times. Otherwise, the function evaluates the predicate a number of times proportional to last - first.

The second template function behaves the same, except that it replaces operator<(X, Y) with pr(X, Y).


fill

template<class FwdIt, class T>
    void fill(FwdIt first, FwdIt last, const T& x);

The template function evaluates *(first + N) = x once for each N in the range [0, last - first).


fill_n

template<class OutIt, class Size, class T>
    void fill_n(OutIt first, Size n, const T& x);

The template function evaluates *(first + N) = x once for each N in the range [0, n).


find

template<class InIt, class T>
    InIt find(InIt first, InIt last, const T& val);

The template function determines the lowest value of N in the range [0, last - first) for which the predicate *(first + N) == val is true. It then returns first + N. If no such value exists, the function returns last. It evaluates the predicate once, at most, for each N.

See the related sample program.


find_end

template<class FwdIt1, class FwdIt2>
    FwdIt1 find_end(FwdIt1 first1, FwdIt1 last1,
        FwdIt2 first2, FwdIt2 last2);
template<class FwdIt1, class FwdIt2, class Pred>
    FwdIt1 find_end(FwdIt1 first1, FwdIt1 last1,
        FwdIt2 first2, FwdIt2 last2, Pred pr);

The first template function determines the highest value of N in the range [0, last1 - first1 - (last2 - first2)) such that for each M in the range [0, last2 - first2), the predicate *(first1 + N + M) == *(first2 + N + M) is true. It then returns first1 + N. If no such value exists, the function returns last1. It evaluates the predicate (last2 - first2) * (last1 - first1 - (last2 - first2) + 1) times, at most.

The second template function behaves the same, except that the predicate is pr(*(first1 + N + M), *(first2 + N + M)).


find_first_of

template<class FwdIt1, class FwdIt2>
    FwdIt1 find_first_of(FwdIt1 first1, FwdIt1 last1,
        FwdIt2 first2, FwdIt2 last2);
template<class FwdIt1, class FwdIt2, class Pred>
    FwdIt1 find_first_of(FwdIt1 first1, FwdIt1 last1,
        FwdIt2 first2, FwdIt2 last2, Pred pr);

The first template function determines the lowest value of N in the range [0, last1 - first1) such that for some M in the range [0, last2 - first2), the predicate *(first1 + N) == *(first2 + M) is true. It then returns first1 + N. If no such value exists, the function returns last1. It evaluates the predicate (last1 - first1) * (last2 - first2) times, at most.

The second template function behaves the same, except that the predicate is pr(*(first1 + N), *(first2 + M)).


find_if

template<class InIt, class Pred>
    InIt find_if(InIt first, InIt last, Pred pr);

The template function determines the lowest value of N in the range [0, last - first) for which the predicate pred(*(first + N)) is true. It then returns first + N. If no such value exists, the function returns last. It evaluates the predicate once, at most, for each N.

See the related sample program.


for_each

template<class InIt, class Fun>
    Fun for_each(InIt first, InIt last, Fun f);

The template function evaluates f(*(first + N)) once for each N in the range [0, last - first). It then returns f. The call f(*(first + N)) must not alter *(first + N).

See the related sample program.


generate

template<class FwdIt, class Gen>
    void generate(FwdIt first, FwdIt last, Gen g);

The template function evaluates *(first + N) = g() once for each N in the range [0, last - first).

See the related sample program.


generate_n

template<class OutIt, class Pred, class Gen>
    void generate_n(OutIt first, Dist n, Gen g);

The template function evaluates *(first + N) = g() once for each N in the range [0, n).

See the related sample program.


includes

template<class InIt1, class InIt2>
    bool includes(InIt1 first1, InIt1 last1,
        InIt2 first2, InIt2 last2);
template<class InIt1, class InIt2, class Pred>
    bool includes(InIt1 first1, InIt1 last1,
        InIt2 first2, InIt2 last2, Pred pr);

The first template function determines whether a value of N exists in the range [0, last2 - first2) such that, for each M in the range [0, last1 - first1), *(first + M) and *(first + N) do not have equivalent ordering, where the elements designated by iterators in the ranges [first1, last1) and [first2, last2) each form a sequence ordered by operator<. If so, the function returns false. If no such value exists, it returns true. Thus, the function determines whether the ordered sequence designated by iterators in the range [first2, last2) has equivalent ordering with some element designated by iterators in the range [first1, last1).

The function evaluates the predicate 2 * ((last1 - first1) + (last2 - first2)) - 1 times, at most.

The second template function behaves the same, except that it replaces operator<(X, Y) with pr(X, Y).

Sample programs: includes and includes (predicate version).


inplace_merge

template<class BidIt>
    void inplace_merge(BidIt first, BidIt middle, BidIt last);
template<class BidIt, class Pred>
    void inplace_merge(BidIt first, BidIt middle, BidIt last, Pred pr);

The first template function reorders the sequences designated by iterators in the ranges [first, middle) and [middle, last), each ordered by operator<, to form a merged sequence of length last - first beginning at first, also ordered by operator<. The merge occurs without altering the relative order of elements within either original sequence. Moreover, for any two elements from different original sequences that have equivalent ordering, the element from the ordered range [first, middle) precedes the other.

The function evaluates the ordering predicate X < Y at most ceil((last - first) * log(last - first)) times. (Given enough temporary storage, it can evaluate the predicate (last - first) - 1 times, at most.)

The second template function behaves the same, except that it replaces operator<(X, Y) with pr(X, Y).

Sample programs: inplace_merge and inplace_merge (predicate version).


iter_swap

template<class FwdIt1, class FwdIt2>
    void iter_swap(FwdIt1 x, FwdIt2 y);

The template function leaves the value originally stored in *y subsequently stored in *x, and the value originally stored in *x subsequently stored in *y.

See the related sample program.


lexicographical_compare

template<class InIt1, class InIt2>
    bool lexicographical_compare(InIt1 first1, InIt1 last1,
        InIt2 first2, InIt2 last2);
template<class InIt1, class InIt2, class Pred>
    bool lexicographical_compare(InIt1 first1, InIt1 last1,
        InIt2 first2, InIt2 last2, Pred pr);

The first template function determines K, the number of elements to compare as the smaller of last1 - first1 and last2 - first2. It then determines the lowest value of N in the range [0, K) for which *(first1 + N) and *(first2 + N) do not have equivalent ordering. If no such value exists, the function returns true only if K < (last2 - first2). Otherwise, it returns true only if *(first1 + N) < *(first2 + N). Thus, the function returns true only if the sequence designated by iterators in the range [first1, last1) is lexicographically less than the other sequence.

The function evaluates the ordering predicate X < Y at most 2 * K times.

The second template function behaves the same, except that it replaces operator<(X, Y) with pr(X, Y).


lower_bound

template<class FwdIt, class T>
    FwdIt lower_bound(FwdIt first, FwdIt last, const T& val);
template<class FwdIt, class T, class Pred>
    FwdIt lower_bound(FwdIt first, FwdIt last, const T& val, Pred pr);

The first template function determines the lowest value of N in the range [0, last - first) such that, for each M in the range [0, N), the predicate *(first + M) < val is true, where the elements designated by iterators in the range [first, last) form a sequence ordered by operator<. It then returns first + N. If no such value exists, the function returns last. Thus, the function determines the lowest position before which val can be inserted in the sequence and still preserve its ordering.

If FwdIt is a random-access iterator type, the function evaluates the ordering predicate X < Y ceil(log(last - first)) + 1 times, at most. Otherwise, the function evaluates the predicate a number of times proportional to last - first.

The second template function behaves the same, except that it replaces operator<(X, Y) with pr(X, Y).

Sample programs: lower_bound and lower_bound (predicate version).


make_heap

template<class RanIt>
    void make_heap(RanIt first, RanIt last);
template<class RanIt, class Pred>
    void make_heap(RanIt first, RanIt last, Pred pr);

The first template function reorders the sequence designated by iterators in the range [first, last) to form a heap ordered by operator<.

The function evaluates the ordering predicate X < Y at most 3 * (last - first) times.

The second template function behaves the same, except that it replaces operator<(X, Y) with pr(X, Y).

Sample programs: heap and heap (predicate version).


max

template<class T>
    const T& max(const T& x, const T& y);
template<class T, class Pred>
    const T& max(const T& x, const T& y, Pred pr);

The first template function returns y if x < y. Otherwise, it returns x. T need supply only a single-argument constructor and a destructor.

The second template function behaves the same, except that it replaces operator<(X, Y) with pr(X, Y).

Microsoft-Specific:
To avoid conflicts with min and max in WINDEF.H, use _MIN and _MAX instead. These macros evaluate to _cpp_min and _cpp_max, respectively.
END Microsoft-Specific


max_element

template<class FwdIt>
    FwdIt max_element(FwdIt first, FwdIt last);
template<class FwdIt, class Pred>
    FwdIt max_element(FwdIt first, FwdIt last, Pred pr);

The first template function determines the lowest value of N in the range [0, last - first) such that, for each M in the range [0, last - first), the predicate *(first + N) < *(first + M) is false. It then returns first + N. Thus, the function determines the lowest position that contains the largest value in the sequence.

The function evaluates the ordering predicate X < Y exactly max((last - first) - 1, 0) times.

The second template function behaves the same, except that it replaces operator<(X, Y) with pr(X, Y).

Sample programs: max_element and max_element (predicate version).


merge

template<class InIt1, class InIt2, class OutIt>
    OutIt merge(InIt1 first1, InIt1 last1,
        InIt2 first2, InIt2 last2, OutIt x);
template<class InIt1, class InIt2, class OutIt, class Pred>
    OutIt merge(InIt1 first1, InIt1 last1,
        InIt2 first2, InIt2 last2, OutIt x, Pred pr);

The first template function determines K, the number of elements to copy as (last1 - first1) + (last2 - first2). It then alternately copies two sequences, designated by iterators in the ranges [first1, last1) and [first2, last2) and each ordered by operator<, to form a merged sequence of length K beginning at x, also ordered by operator<. The function then returns x + K.

The merge occurs without altering the relative order of elements within either sequence. Moreover, for any two elements from different sequences that have equivalent ordering, the element from the ordered range [first1, last1) precedes the other. Thus, the function merges two ordered sequences to form another ordered sequence.

If x and first1 designate regions of storage, the range [x, x + K) must not overlap the range [first1, last1). If x and first2 designate regions of storage, the range [x, x + K) must not overlap the range [first2, last2). The function evaluates the ordering predicate X < Y at most K - 1 times.

The second template function behaves the same, except that it replaces operator<(X, Y) with pr(X, Y).

Sample programs: merge and merge (predicate version).


min

template<class T>
    const T& min(const T& x, const T& y);
template<class T, class Pred>
    const T& min(const T& x, const T& y, Pred pr);

The first template function returns y if y < x. Otherwise it returns x. T need supply only a single-argument constructor and a destructor.

The second template function behaves the same, except that it replaces operator<(X, Y) with pr(X, Y).

Microsoft-Specific:
To avoid conflicts with min and max in WINDEF.H, use _MIN and _MAX instead. These macros evaluate to _cpp_min and _cpp_max, respectively.
END Microsoft-Specific


min_element

template<class FwdIt>
    FwdIt min_element(FwdIt first, FwdIt last);
template<class FwdIt, class Pred>
    FwdIt min_element(FwdIt first, FwdIt last, Pred pr);

The first template function determines the lowest value of N in the range [0, last - first) such that, for each M in the range [0, last - first), the predicate *(first + M) < *(first + N) is false. It then returns first + N. Thus, the function determines the lowest position that contains the smallest value in the sequence.

The function evaluates the ordering predicate X < Y exactly max((last - first) - 1, 0) times.

The second template function behaves the same, except that it replaces operator<(X, Y) with pr(X, Y).

Sample programs: min_element and min_element (predicate version).


mismatch

template<class InIt1, class InIt2>
    pair<InIt1, InIt2> mismatch(InIt1 first, InIt1 last, InIt2 x);
template<class InIt1, class InIt2, class Pred>
    pair<InIt1, InIt2> mismatch(InIt1 first, InIt1 last,
        InIt2 x, Pred pr);

The first template function determines the lowest value of N in the range [0, last1 - first1) for which the predicate !(*(first1 + N) == *(first2 + N)) is true. It then returns pair (first1 + N, first2 + N). If no such value exists, N has the value last1 - first1. The function evaluates the predicate once, at most, for each N.

The second template function behaves the same, except that the predicate is pr(*(first1 + N), *(first2 + N)).


next_permutation

template<class BidIt>
    bool next_permutation(BidIt first, BidIt last);
template<class BidIt, class Pred>
    bool next_permutation(BidIt first, BidIt last, Pred pr);

The first template function determines a repeating sequence of permutations, whose initial permutation occurs when the sequence designated by iterators in the range [first, last) is ordered by operator<. (The elements are sorted in ascending order.) It then reorders the elements in the sequence, by evaluating swap (X, Y) for the elements X and Y zero or more times, to form the next permutation. The function returns true only if the resulting sequence is not the initial permutation. Otherwise, the resultant sequence is the one next larger lexicographically than the original sequence. No two elements may have equivalent ordering.

The function evaluates swap(X, Y) at most (last - first) / 2 times.

The second template function behaves the same, except that it replaces operator<(X, Y) with pr(X, Y).

Sample programs: next_permutation and next_permutation (predicate version).


nth_element

template<class RanIt>
    void nth_element(RanIt first, RanIt nth, RanIt last);
template<class RanIt, class Pred>
    void nth_element(RanIt first, RanIt nth, RanIt last, Pred pr);

The first template function reorders the sequence designated by iterators in the range [first, last) such that for each N in the range [0, nth - first) and for each M in the range [nth - first, last - first), the predicate !(*(first + M) < *(first + N)) is true. Moreover, for N equal to nth - first and for each M in the range (nth - first, last - first) the predicate !(*(first + M) < *(first + N)) is true. Thus, if nth != last, the element *nth is in its proper position if elements of the entire sequence were sorted in ascending order, ordered by operator<. Any elements before this one belong before it in the sort sequence, and any elements following it belong after it.

The function evaluates the ordering predicate X < Y a number of times proportional to last - first, on average.

The second template function behaves the same, except that it replaces operator<(X, Y) with pr(X, Y).

Sample programs: nth_element and nth_element (predicate version).


partial_sort

template<class RanIt>
    void partial_sort(RanIt first, RanIt middle, RanIt last);
template<class RanIt, class Pred>
    void partial_sort(RanIt first, RanIt middle, RanIt last, Pred pr);

The first template function reorders the sequence designated by iterators in the range [first, last) such that for each N in the range [0, middle - first) and for each M in the range (N, last - first), the predicate !(*(first + M) < *(first + N)) is true. Thus, the smallest middle - first elements of the entire sequence are sorted in ascending order, ordered by operator<. The order of the remaining elements is otherwise unspecified.

The function evaluates the ordering predicate X < Y ceil((last - first) * log(middle - first)) times, at most.

The second template function behaves the same, except that it replaces operator<(X, Y) with pr(X, Y).

Sample programs: partial_sort and partial_sort (predicate version).


partial_sort_copy

template<class InIt, class RanIt>
    RanIt partial_sort_copy(InIt first1, InIt last1,
        RanIt first2, RanIt last2);
template<class InIt, class RanIt, class Pred>
    RanIt partial_sort_copy(InIt first1, InIt last1,
        RanIt first2, RanIt last2, Pred pr);

The first template function determines K, the number of elements to copy as the smaller of last1 - first1 and last2 - first2. It then copies and reorders K of the sequence designated by iterators in the range [first1, last1) such that the K elements copied to first2 are ordered by operator<. Moreover, for each N in the range [0, K) and for each M in the range (0, last1 - first1) corresponding to an uncopied element, the predicate !(*(first2 + M) < *(first1 + N)) is true. Thus, the smallest K elements of the entire sequence designated by iterators in the range [first1, last1) are copied and sorted in ascending order to the range [first2, first2 + K).

The function evaluates the ordering predicate X < Y ceil((last - first) * log(K)) times, at most.

The second template function behaves the same, except that it replaces operator<(X, Y) with pr(X, Y).

Sample programs: one and one (predicate version).


partition

template<class BidIt, class Pred>
    BidIt partition(BidIt first, BidIt last, Pred pr);

The template function reorders the sequence designated by iterators in the range [first, last) and determines the value K such that for each N in the range [0, K), the predicate pr(*(first + N)) is true, and for each N in the range [K, last - first), the predicate pr(*(first + N)) is false. The function then returns first + K.

The predicate must not alter its operand. The function evaluates pr(*(first + N)) exactly last - first times, and swaps (last - first) / 2 pairs of elements, at most.

See the related sample program.


pop_heap

template<class RanIt>
    void pop_heap(RanIt first, RanIt last);
template<class RanIt, class Pred>
    void pop_heap(RanIt first, RanIt last, Pred pr);

The first template function reorders the sequence designated by iterators in the range [first, last) to form a new heap, ordered by operator< and designated by iterators in the range [first, last - 1), leaving the original element at *first subsequently at *(last - 1). The original sequence must designate an existing heap, also ordered by operator<. Thus, first != last must be true and *(last - 1) is the element to remove from (pop off) the heap.

The function evaluates the ordering predicate X < Y ceil(2 * log(last - first)) times, at most.

The second template function behaves the same, except that it replaces operator<(X, Y) with pr(X, Y).

Sample programs: heap and heap (predicate version).


prev_permutation

template<class BidIt>
    bool prev_permutation(BidIt first, BidIt last);
template<class BidIt, class Pred>
    bool prev_permutation(BidIt first, BidIt last, Pred pr);

The first template function determines a repeating sequence of permutations, whose initial permutation occurs when the sequence designated by iterators in the range [first, last) is the reverse of one ordered by operator<. (The elements are sorted in descending order.) It then reorders the elements in the sequence, by evaluating swap (X, Y) for the elements X and Y zero or more times, to form the next permutation. The function returns true only if the resulting sequence is not the initial permutation. Otherwise, the resultant sequence is the one next smaller lexicographically than the original sequence. No two elements may have equivalent ordering.

The function evaluates swap(X, Y) (last - first) / 2 times, at most.

The second template function behaves the same, except that it replaces operator<(X, Y) with pr(X, Y).

See the related sample program.


push_heap

template<class RanIt>
    void push_heap(RanIt first, RanIt last);
template<class RanIt, class Pred>
    void push_heap(RanIt first, RanIt last, Pred pr);

The first template function reorders the sequence designated by iterators in the range [first, last) to form a new heap ordered by operator<. Iterators in the range [first, last - 1) must designate an existing heap, also ordered by operator<. Thus, first != last must be true and *(last - 1) is the element to add to (push on) the heap.

The function evaluates the ordering predicate X < Y ceil(log(last - first)) times, at most.

The second template function behaves the same, except that it replaces operator<(X, Y) with pr(X, Y).

Sample programs: heap and heap (predicate version).


random_shuffle

template<class RanIt>
    void random_shuffle(RanIt first, RanIt last);
template<class RanIt, class Fun>
    void random_shuffle(RanIt first, RanIt last, Fun& f);

The first template function evaluates swap (*(first + N), *(first + M)) once for each N in the range [1, last - first), where M is a value from some uniform random distribution over the range [0, N). Thus, the function randomly shuffles the order of elements in the sequence.

The second template function behaves the same, except that M is (Dist)f((Dist)N), where Dist is the type iterator_traits :: distance_type.

Sample programs: random_shuffle and random_shuffle (predicate version).


remove

template<class FwdIt, class T>
    FwdIt remove(FwdIt first, FwdIt last, const T& val);

The template function effectively assigns first to X, then executes the statement:

if (!(*(first + N) == val))
    *X++ = *(first + N);

once for each N in the range [0, last - first). It then returns X. Thus, the function removes from the sequence all elements for which the predicate *(first + N) == val is true, without altering the relative order of remaining elements, and returns the iterator value that designates the end of the revised sequence.

See the related sample program.


remove_copy

template<class InIt, class OutIt, class T>
    OutIt remove_copy(InIt first, InIt last, OutIt x, const T& val);

The template function effectively executes the statement:

if (!(*(first + N) == val))
    *x++ = *(first + N);

once for each N in the range [0, last - first). It then returns x. Thus, the function removes from the sequence all elements for which the predicate *(first + N) == val is true, without altering the relative order of remaining elements, and returns the iterator value that designates the end of the revised sequence.

If x and first designate regions of storage, the range [x, x + (last - first)) must not overlap the range [first, last).

See the related sample program.


remove_copy_if

template<class InIt, class OutIt, class Pred>
    OutIt remove_copy_if(InIt first, InIt last, OutIt x, Pred pr);

The template function effectively executes the statement:

if (!pr(*(first + N)))
    *x++ = *(first + N);

once for each N in the range [0, last - first). It then returns x. Thus, the function removes from the sequence all elements for which the predicate pr(*(first + N)) is true, without altering the relative order of remaining elements, and returns the iterator value that designates the end of the revised sequence.

If x and first designate regions of storage, the range [x, x + (last - first)) must not overlap the range [first, last).

See the related sample program.


remove_if

template<class FwdIt, class Pred>
    FwdIt remove_if(FwdIt first, FwdIt last, Pred pr);

The template function effectively assigns first to X, then executes the statement:

if (!pr(*(first + N)))
    *X++ = *(first + N);

once for each N in the range [0, last - first). It then returns X. Thus, the function removes from the sequence all elements for which the predicate pr(*(first + N)) is true, without altering the relative order of remaining elements, and returns the iterator value that designates the end of the revised sequence.

See the related sample program.


replace

template<caass FwdIt, class T>
    void replace(FwdIt first, FwdIt last,
        const T& vold, const T& vnew);

The template function executes the statement:

if (*(first + N) == vold)
    *(first + N) = vnew;

once for each N in the range [0, last - first).

See the related sample program.


replace_copy

template<class InIt, class OutIt, class T>
    OutIt replace_copy(InIt first, InIt last, OutIt x,
        const T& vold, const T& vnew);

The template function executes the statement:

if (*(first + N) == vold)
    *(x + N) = vnew;
else
    *(x + N) = *(first + N)

once for each N in the range [0, last - first).

If x and first designate regions of storage, the range [x, x + (last - first)) must not overlap the range [first, last).

See the related sample program.


replace_copy_if

template<class InIt, class OutIt, class Pred, class T>
    OutIt replace_copy_if(InIt first, InIt last, OutIt x,
        Pred pr, const T& val);

The template function executes the statement:

if (pr(*(first + N)))
    *(x + N) = val;
else
    *(x + N) = *(first + N)

once for each N in the range [0, last - first).

If x and first designate regions of storage, the range [x, x + (last - first)) must not overlap the range [first, last).

See the related sample program.


replace_if

template<class FwdIt, class Pred, class T>
    void replace_if(FwdIt first, FwdIt last,
        Pred pr, const T& val);

The template function executes the statement:

if (pr(*(first + N)))
    *(first + N) = val;

once for each N in the range [0, last - first).

See the related sample program.


reverse

template<class BidIt>
    void reverse(BidIt first, BidIt last);

The template function evaluates swap (*(first + N), *(last - 1 - N) once for each N in the range [0, (last - first) / 2). Thus, the function reverses the order of elements in the sequence.

See the related sample program.


reverse_copy

template<class BidIt, class OutIt>
    OutIt reverse_copy(BidIt first, BidIt last, OutIt x);

The template function evaluates *(x + N) = *(last - 1 - N) once for each N in the range [0, last - first). It then returns x + (last - first). Thus, the function reverses the order of elements in the sequence that it copies.

If x and first designate regions of storage, the range [x, x + (last - first)) must not overlap the range [first, last).

See the related sample program.


rotate

template<class FwdIt>
    void rotate(FwdIt first, FwdIt middle, FwdIt last);

The template function leaves the value originally stored in *(first + (N + (middle - last)) % (last - first)) subsequently stored in *(first + N) for each N in the range [0, last - first). Thus, if a ''left'' shift by one element leaves the element originally stored in *(first + (N + 1) % (last - first)) subsequently stored in *(first + N), then the function can be said to rotate the sequence either left by middle - first elements or right by last - middle elements. Both [first, middle) and [middle, last) must be valid ranges. The function swaps at most last - first pairs of elements.

See the related sample program.


rotate_copy

template<class FwdIt, class OutIt>
    OutIt rotate_copy(FwdIt first, FwdIt middle, FwdIt last, OutIt x);

The template function evaluates *(x + N) = *(first + (N + (middle - first)) % (last - first)) once for each N in the range [0, last - first). Thus, if a ''left'' shift by one element leaves the element originally stored in *(first + (N + 1) % (last - first)) subsequently stored in *(first + N), then the function can be said to rotate the sequence either left by middle - first elements or right by last - middle elements as it copies. Both [first, middle) and [middle, last) must be valid ranges.

If x and first designate regions of storage, the range [x, x + (last - first)) must not overlap the range [first, last).

See the related sample program.


search

template<class FwdIt1, class FwdIt2>
    FwdIt1 search(FwdIt1 first1, FwdIt1 last1,
        FwdIt2 first2, FwdIt2 last2);
template<class FwdIt1, class FwdIt2, class Pred>
    FwdIt1 search(FwdIt1 first1, FwdIt1 last1,
        FwdIt2 first2, FwdIt2 last2, Pred pr);

The first template function determines the lowest value of N in the range [0, (last1 - first1) - (last2 - first2)) such that for each M in the range [0, last2 - first2), the predicate *(first1 + N + M) == *(first2 + M) is true. It then returns first1 + N. If no such value exists, the function returns last1. It evaluates the predicate (last2 - first2) * (last1 - first1) times, at most.

The second template function behaves the same, except that the predicate is pr(*(first1 + N + M), *(first2 + M)).


search_n

template<class FwdIt, class Dist, class T>
    FwdIt search_n(FwdIt first, FwdIt last,
        Dist n, const T& val);
template<class FwdIt, class Dist, class T, class Pred>
    FwdIt search_n(FwdIt first, FwdIt last,
        Dist n, const T& val, Pred pr);

The first template function determines the lowest value of N in the range [0, (last - first) - n) such that for each M in the range [0, n), the predicate *(first + N + M) == val is true. It then returns first + N. If no such value exists, the function returns last. It evaluates the predicate n * (last - first) times, at most.

The second template function behaves the same, except that the predicate is pr(*(first + N + M), val).


set_difference

template<class InIt1, class InIt2, class OutIt>
    OutIt set_difference(InIt1 first1, InIt1 last1,
        InIt2 first2, InIt2 last2, OutIt x);
template<class InIt1, class InIt2, class OutIt, class Pred>
    OutIt set_difference(InIt1 first1, InIt1 last1,
        InIt2 first2, InIt2 last2, OutIt x, Pred pr);

The first template function alternately copies values from two sequences designated by iterators in the ranges [first1, last1) and [first2, last2), both ordered by operator<, to form a merged sequence of length K beginning at x, also ordered by operator<. The function then returns x + K.

The merge occurs without altering the relative order of elements within either sequence. Moreover, for two elements from different sequences that have equivalent ordering that would otherwise be copied to adjacent elements, the function copies only the element from the ordered range [first1, last1) and skips the other. An element from one sequence that has equivalent ordering with no element from the other sequence is copied from the ordered range [first1, last1) and skipped from the other. Thus, the function merges two ordered sequences to form another ordered sequence that is effectively the difference of two sets.

If x and first1 designate regions of storage, the range [x, x + K) must not overlap the range [first1, last1). If x and first2 designate regions of storage, the range [x, x + K) must not overlap the range [first2, last2). The function evaluates the ordering predicate X < Y at most 2 * ((last1 - first1) + (last2 - first2)) - 1 times.

The second template function behaves the same, except that it replaces operator<(X, Y) with pr(X, Y).


set_intersection

template<class InIt1, class InIt2, class OutIt>
    OutIt set_intersection(InIt1 first1, InIt1 last1,
        InIt2 first2, InIt2 last2, OutIt x);
template<class InIt1, class InIt2, class OutIt, class Pred>
    OutIt set_intersection(InIt1 first1, InIt1 last1,
        InIt2 first2, InIt2 last2, OutIt x, Pred pr);

The first template function alternately copies values from two sequences designated by iterators in the ranges [first1, last1) and [first2, last2), both ordered by operator<, to form a merged sequence of length K beginning at x, also ordered by operator<. The function then returns x + K.

The merge occurs without altering the relative order of elements within either sequence. Moreover, for two elements from different sequences that have equivalent ordering that would otherwise be copied to adjacent elements, the function copies only the element from the ordered range [first1, last1) and skips the other. An element from one sequence that has equivalent ordering with no element from the other sequence is also skipped. Thus, the function merges two ordered sequences to form another ordered sequence that is effectively the intersection of two sets.

If x and first1 designate regions of storage, the range [x, x + K) must not overlap the range [first1, last1). If x and first2 designate regions of storage, the range [x, x + K) must not overlap the range [first2, last2). The function evaluates the ordering predicate X < Y at most 2 * ((last1 - first1) + (last2 - first2)) - 1 times.

The second template function behaves the same, except that it replaces operator<(X, Y) with pr(X, Y).


set_symmetric_difference

template<class InIt1, class InIt2, class OutIt>
    OutIt set_symmetric_difference(InIt1 first1, InIt1 last1,
        InIt2 first2, InIt2 last2, OutIt x);
template<class InIt1, class InIt2, class OutIt, class Pred>
    OutIt set_symmetric_difference(InIt1 first1, InIt1 last1,
        InIt2 first2, InIt2 last2, OutIt x, Pred pr);

The first template function alternately copies values from two sequences designated by iterators in the ranges [first1, last1) and [first2, last2), both ordered by operator<, to form a merged sequence of length K beginning at x, also ordered by operator<. The function then returns x + K.

The merge occurs without altering the relative order of elements within either sequence. Moreover, for two elements from different sequences that have equivalent ordering that would otherwise be copied to adjacent elements, the function copies neither element. An element from one sequence that has equivalent ordering with no element from the other sequence is copied. Thus, the function merges two ordered sequences to form another ordered sequence that is effectively the symmetric difference of two sets.

If x and first1 designate regions of storage, the range [x, x + K) must not overlap the range [first1, last1). If x and first2 designate regions of storage, the range [x, x + K) must not overlap the range [first2, last2). The function evaluates the ordering predicate X < Y at most 2 * ((last1 - first1) + (last2 - first2)) - 1 times.

The second template function behaves the same, except that it replaces operator<(X, Y) with pr(X, Y).


set_union

template<class InIt1, class InIt2, class OutIt>
    OutIt set_union(InIt1 first1, InIt1 last1,
        InIt2 first2, InIt2 last2, OutIt x);
template<class InIt1, class InIt2, class OutIt, class Pred>
    OutIt set_union(InIt1 first1, InIt1 last1,
        InIt2 first2, InIt2 last2, OutIt x, Pred pr);

The first template function alternately copies values from two sequences designated by iterators in the ranges [first1, last1) and [first2, last2), both ordered by operator<, to form a merged sequence of length K beginning at x, also ordered by operator<. The function then returns x + K.

The merge occurs without altering the relative order of elements within either sequence. Moreover, for two elements from different sequences that have equivalent ordering that would otherwise be copied to adjacent elements, the function copies only the element from the ordered range [first1, last1) and skips the other. Thus, the function merges two ordered sequences to form another ordered sequence that is effectively the union of two sets.

If x and first1 designate regions of storage, the range [x, x + K) must not overlap the range [first1, last1). If x and first2 designate regions of storage, the range [x, x + K) must not overlap the range [first2, last2). The function evaluates the ordering predicate X < Y at most 2 * ((last1 - first1) + (last2 - first2)) - 1 times.

The second template function behaves the same, except that it replaces operator<(X, Y) with pr(X, Y).


sort

template<class RanIt>
    void sort(RanIt first, RanIt last);
template<class RanIt, class Pred>
    void sort(RanIt first, RanIt last, Pred pr);

The first template function reorders the sequence designated by iterators in the range [first, last) to form a sequence ordered by operator<. Thus, the elements are sorted in ascending order.

The function evaluates the ordering predicate X < Y at most ceil((last - first) * log(last - first)) times.

The second template function behaves the same, except that it replaces operator<(X, Y) with pr(X, Y).


sort_heap

template<class RanIt>
    void sort_heap(RanIt first, RanIt last);
template<class RanIt, class Pred>
    void sort_heap(RanIt first, RanIt last, Pred pr);

The first template function reorders the sequence designated by iterators in the range [first, last) to form a sequence that is ordered by operator<. The original sequence must designate a heap, also ordered by operator<. Thus, the elements are sorted in ascending order.

The function evaluates the ordering predicate X < Y at most ceil((last - first) * log(last - first)) times.

The second template function behaves the same, except that it replaces operator<(X, Y) with pr(X, Y).

Sample programs: heap and heap (predicate version).


stable_partition

template<class FwdIt, class Pred>
    FwdIt stable_partition(FwdIt first, FwdIt last, Pred pr);

The template function reorders the sequence designated by iterators in the range [first, last) and determines the value K such that for each N in the range [0, K) the predicate pr(*(first + N)) is true, and for each N in the range [K, last - first) the predicate pr(*(first + N)) is false. It does so without altering the relative order of either the elements designated by indexes in the range [0, K) or the elements designated by indexes in the range [K, last - first). The function then returns first + K.

The predicate must not alter its operand. The function evaluates pr(*(first + N)) exactly last - first times, and swaps at most ceil((last - first) * log(last - first)) pairs of elements. (Given enough temporary storage, it can replace the swaps with 2 * (last - first) assignments, at most.)


stable_sort

template<class RanIt>
    void stable_sort(RanIt first, RanIt last);
template<class RanIt, class Pred>
    void stable_sort(RanIt first, RanIt last, Pred pr);

The first template function reorders the sequence designated by iterators in the range [first, last) to form a sequence ordered by operator<. It does so without altering the relative order of elements that have equivalent ordering. Thus, the elements are sorted in ascending order.

The function evaluates the ordering predicate X < Y at most ceil((last - first) * log2(last - first)) times. (Given enough temporary storage, it can evaluate the predicate ceil((last - first) * log(last - first)) times, at most.)

The second template function behaves the same, except that it replaces operator<(X, Y) with pr(X, Y).


swap

template<class T>
    void swap(T& x, T& y);

The template function leaves the value originally stored in y subsequently stored in x, and the value originally stored in x subsequently stored in y.


swap_ranges

template<class FwdIt1, class FwdIt2>
    FwdIt2 swap_ranges(FwdIt1 first, FwdIt1 last, FwdIt2 x);

The template function evaluates swap (*(first + N), *(x + N)) once for each N in the range [0, last - first). It then returns x + (last - first). If x and first designate regions of storage, the range [x, x + (last - first)) must not overlap the range [first, last).


transform

template<class InIt, class OutIt, class Unop>
    OutIt transform(InIt first, InIt last, OutIt x, Unop uop);
template<class InIt1, class InIt2, class OutIt, class Binop>
    OutIt transform(InIt1 first1, InIt1 last1, InIt2 first2,
        OutIt x, Binop bop);

The first template function evaluates *(x + N) = uop(*(first + N)) once for each N in the range [0, last - first). It then returns x + (last - first). The call uop(*(first + N)) must not alter *(first + N).

The second template function evaluates *(x + N) = bop(*(first1 + N), *(first2 + N)) once for each N in the range [0, last1 - first1). It then returns x + (last1 - first1). The call bop(*(first1 + N), *(first2 + N)) must not alter either *(first1 + N) or *(first2 + N).


unique

template<class FwdIt>
    FwdIt unique(FwdIt first, FwdIt last);
template<class FwdIt, class Pred>
    FwdIt unique(FwdIt first, FwdIt last, Pred pr);

The first template function effectively assigns first to X, then executes the statement:

if (N == 0 || !(*(first + N) == V))
    V = *(first + N), *X++ = V;

once for each N in the range [0, last - first). It then returns X. Thus, the function repeatedly removes from the sequence the second of a pair of elements for which the predicate *(first + N) == *(first + N - 1) is true, until only the first of a sequence of equal elements survives. It does so without altering the relative order of remaining elements, and returns the iterator value that designates the end of the revised sequence. The function evaluates the predicate last - first times, at most.

The second template function behaves the same, except that it executes the statement:

if (N == 0 || !pr(*(first + N), V))
    V = *(first + N), *X++ = V;


unique_copy

template<class InIt, class OutIt>
    OutIt unique_copy(InIt first, InIt last, OutIt x);
template<class InIt, class OutIt, class Pred>
    OutIt unique_copy(InIt first, InIt last, OutIt x, Pred pr);

The first template function effectively executes the statement:

if (N == 0 || !(*(first + N) == V))
    V = *(first + N), *x++ = V;

once for each N in the range [0, last - first). It then returns x. Thus, the function repeatedly removes from the sequence it copies the second of a pair of elements for which the predicate *(first + N) == *(first + N - 1) is true, until only the first of a sequence of equal elements survives. It does so without altering the relative order of remaining elements, and returns the iterator value that designates the end of the copied sequence.

If x and first designate regions of storage, the range [x, x + (last - first)) must not overlap the range [first, last).

The second template function behaves the same, except that it executes the statement:

if (N == 0 || !pr(*(first + N), V))
    V = *(first + N), *x++ = V;


upper_bound

template<class FwdIt, class T>
    FwdIt upper_bound(FwdIt first, FwdIt last, const T& val);
template<class FwdIt, class T, class Pred>
    FwdIt upper_bound(FwdIt first, FwdIt last, const T& val, Pred pr);

The first template function determines the highest value of N in the range [0, last - first) such that, for each M in the range [0, N) the predicate *(first + M) < val is true, where the elements designated by iterators in the range [first, last) form a sequence ordered by operator<. It then returns first + N. If no such value exists, the function returns last. Thus, the function determines the highest position before which val can be inserted into the sequence and still preserve its ordering.

If FwdIt is a random-access iterator type, the function evaluates the ordering predicate X < Y ceil(log(last - first)) + 1 times at most. Otherwise, the function evaluates the predicate a number of times proportional to last - first.

The second template function behaves the same, except that it replaces operator<(X, Y) with pr(X, Y).

Sample programs: upper_bound and upper_bound (predicate version).


 <bitset>

<bitset>

namespace std {
template<size_t N>
    class bitset;
//    TEMPLATE FUNCTIONS
template<class E, class T, size_t N>
    basic_istream<E, T>& operator>>(basic_istream<E, T>& is,
        bitset<N>& x);
template<class E, class T, size_t N>
    basic_ostream<E, T>& operator<<(basic_ostream<E, T>& os,
        const bitset<N>& x);
    };

Include the standard header <bitset> to define the template class bitset and two supporting templates.


bitset

any · at · bitset · bitset_size · count · element_type · flip · none · operator!= · operator&= · operator<< · operator<<= · operator== · operator>> · operator>>= · operator[] · operator^= · operator|= · operator~ · reference · reset · set · size · test · to_string · to_ulong

template<size_t N>
    class bitset {
public:
    typedef bool element_type;
    class reference;
    bitset();
    bitset(unsigned long val);
    template<class E, class T, class A>
        explicit bitset(const string<E, T, A>& str,
            string<E, T, A>size_type pos = 0,
            string<E, T, A>size_type n = string<E, T, A>::npos);
    bitset<N>& operator&=(const bitset<N>& rhs);
    bitset<N>& operator|=(const bitset<N>& rhs);
    bitset<N>& operator^=(const bitset<N>& rhs);
    bitset<N>& operator<<=(const bitset<N>& pos);
    bitset<N>& operator>>=(const bitset<N>& pos);
    bitset<N>& set();
    bitset<N>& set(size_t pos, bool val = true);
    bitset<N>& reset();
    bitset<N>& reset(size_t pos);
    bitset<N>& flip();
    bitset<N>& flip(size_t pos);
    reference operator[](size_t pos);
    bool operator[](size_t pos) const;
    reference at(size_t pos);
    bool at(size_t pos) const;
    unsigned long to_ulong() const;
    template<class E, class T, class A>
        string to_string() const;
    size_t count() const;
    size_t size() const;
    bool operator==(const bitset<N>& rhs) const;
    bool operator!=(const bitset<N>& rhs) const;
    bool test(size_t pos) const;
    bool any() const;
    bool none() const;
    bitset<N> operator<<(size_t pos) const;
    bitset<N> operator>>(size_t pos) const;
    bitset<N> operator~();
    static const size_t bitset_size = N;
    };

The template class describes an object that stores a sequence of N bits. A bit is set if its value is 1, reset if its value is 0. To flip a bit is to change its value from 1 to 0 or from 0 to 1. When converting between an object of class bitset<N> and an object of some integral type, bit position j corresponds to the bit value 1 << j. The integral value corresponding to two or more bits is the sum of their bit values.


bitset::any

bool any() const;

The member function returns true if any bit is set in the bit sequence.


bitset::at

bool at(size_type pos) const;
reference at(size_type pos);

The member function returns an object of class reference, which designates the bit at position pos, if the object can be modified. Otherwise, it returns the value of the bit at position pos in the bit sequence. If that position is invalid, the function throws an object of class out_of_range.


bitset::bitset

bitset();
bitset(unsigned long val);
explicit bitset(const string& str,
    size_t pos = 0, size_t n = -1);

The first constructor resets all bits in the bit sequence. The second constructor sets only those bits at position j for which val & 1 << j is nonzero.

The third constructor determines the initial bit values from elements of a string determined from str. If str. size () < pos, the constructor throws out_of_range. Otherwise, the effective length of the string rlen is the smaller of n and str.size() - pos. If any of the rlen elements beginning at position pos is other than 0 or 1, the constructor throws invalid_argument. Otherwise, the constructor sets only those bits at position j for which the element at position pos + j is 1.

In this implementation, if a translator does not support member template functions, the template:

template<class E, class T, class A>
    explicit bitset(const string<E, T, A>& str,
        string<E, T, A>size_type pos = 0,
        string<E, T, A>size_type n = string<E, T, A>::npos);

is replaced by:

explicit bitset(const string& str,
    size_t pos = 0, size_t n = -1);


bitset::bitset_size

static const size_t bitset_size = N;

The const static member is initialized to the template parameter N.


bitset::count

size_t count() const;

The member function returns the number of bits set in the bit sequence.


bitset::element_type

typedef bool element_type;

The type is a synonyn for bool.


bitset::flip

bitset<N>& flip();
bitset<N>& flip(size_t pos);

The first member function flips all bits in the bit sequence, then returns *this. The second member function throws out_of_range if size () <= pos. Otherwise, it flips the bit at position pos, then returns *this.


bitset::none

bool none() const;

The member function returns true if none of the bits are set in the bit sequence.


bitset::operator!=

bool operator !=(const bitset<N>& rhs) const;

The member operator function returns true only if the bit sequence stored in *this differs from the one stored in rhs.


bitset::operator&=

bitset<N>& operator&=(const bitset<N>& rhs);

The member operator function replaces each element of the bit sequence stored in *this with the logical AND of its previous value and the corresponding bit in rhs. The function returns *this.


bitset::operator<<

bitset<N> operator<<(const bitset<N>& pos);

The member operator function returns bitset(*this) <<= pos.


bitset::operator<<=

bitset<N>& operator<<=(const bitset<N>& pos);

The member operator function replaces each element of the bit sequence stored in *this with the element pos positions earlier in the sequence. If no such earlier element exists, the function clears the bit. The function returns *this.


bitset::operator==

bool operator ==(const bitset<N>& rhs) const;

The member operator function returns true only if the bit sequence stored in *this is the same as the one stored in rhs.


bitset::operator>>

bitset<N> operator>>(const bitset<N>& pos);

The member operator function returns bitset(*this) >>= pos.


bitset::operator>>=

bitset<N>& operator>>=(const bitset<N>& pos);

The member function replaces each element of the bit sequence stored in *this with the element pos positions later in the sequence. If no such later element exists, the function clears the bit. The function returns *this.


bitset::operator[]

bool operator[](size_type pos) const;
reference operator(size_type pos);

The member function returns an object of class reference, which designates the bit at position pos, if the object can be modified. Otherwise, it returns the value of the bit at position pos in the bit sequence. If that position is invalid, the behavior is undefined.


bitset::operator^=

bitset<N>& operator^=(const bitset<N>& rhs);

The member operator function replaces each element of the bit sequence stored in *this with the logical EXCLUSIVE OR of its previous value and the corresponding bit in rhs. The function returns *this.


bitset::operator|=

bitset<N>& operator|=(const bitset<N>& rhs);

The member operator function replaces each element of the bit sequence stored in *this with the logical OR of its previous value and the corresponding bit in rhs. The function returns *this.


bitset::operator~

bitset<N> operator~();

The member operator function returns bitset(*this). flip ().


bitset::reference

class reference {
public:
    reference& operator=(bool b};
    reference& operator=(const reference& x);
    bool operator~() const;
    operator bool() const;
    reference& flip();
    };

The member class describes an object that designates an individual bit within the bit sequence. Thus, for b an object of type bool, x and y objects of type bitset<N>, and i and j valid positions within such an object, the member functions of class reference ensure that (in order):

  • x[i] = b stores b at bit position i in x
  • x[i] = y[j] stores the value of the bit y[j] at bit position i in x
  • b = ~x[i] stores the flipped value of the bit x[i] in b
  • b = x[i] stores the value of the bit x[i] in b
  • x[i].flip() stores the flipped value of the bit x[i] back at bit position i in x


bitset::reset

bitset<N>& reset();
bitset<N>& reset(size_t pos);

The first member function resets all bits in the bit sequence, then returns *this. The second member function throws out_of_range if size () <= pos. Otherwise, it resets the bit at position pos, then returns *this.


bitset::set

bitset<N>& set();
bitset<N>& set(size_t pos, bool val = true);

The first member function resets all bits in the bit sequence, then returns *this. The second member function throws out_of_range if size () <= pos. Otherwise, it stores val in the bit at position pos, then returns *this.


bitset::size

size_t size() const;

The member function returns N.


bitset::test

bool test(size_t pos, bool val = true);

The member function throws out_of_range if size () <= pos. Otherwise, it returns true only if the bit at position pos is set.


bitset::to_string

string to_string() const;

The member function constructs str, an object of class string. For each bit in the bit sequence, the function appends 1 if the bit is set, otherwise 0. The last element appended to str corresponds to bit position zero. The function returns str.

In this implementation, if a translator does not support member template functions, the template:

template<class E, class T, class A>
    string to_string() const;

is replaced by:

string to_string() const;


bitset::to_ulong

unsigned long to_ulong() const;

The member function throws overflow_error if any bit in the bit sequence has a bit value that cannot be represented as a value of type unsigned long. Otherwise, it returns the sum of the bit values in the bit sequence.


operator<<

template<class E, class T, size_t N>
    basic_ostream<E, T>& operator<<(basic_ostream<E, T>& os,
        const bitset<N>& x);

The template function overloads operator<< to insert a text representation of the bit sequence in os. It effectively executes os << x. to_string <E, char_traits<E>, allocator<E> >(), then returns os.


operator>>

template<class E, class T, size_t N>
    basic_istream<E, T>& operator>>(basic_istream<E, T>&
        is, bitset<N>& x);

The template function overloads operator>> to store in x the value bitset(str), where str is an object of type basic_string <E, T, allocator<E> >& extracted from is. The function extracts elements and appends them to str until:

  • N elements have been extracted and stored.
  • end-of-file occurs on the input sequence.
  • the next input element is neither 0 nor 1, in which case the input element is not extracted.

If the function stores no characters in str, it calls is. setstate (ios_base::failbit). In any case, it returns is.


 <cassert>

<cassert>

namespace std {#include <assert.h> };

Include the standard header <cassert> to effectively include the standard header <assert.h> within the std namespace.


 <cctype>

<cctype>

namespace std {#include <ctype.h> };

Include the standard header <cctype> to effectively include the standard header <ctype.h> within the std namespace.


 <cerrno>

<cerrno>

namespace std {#include <errno.h> };

Include the standard header <cerrno> to effectively include the standard header <errno.h> within the std namespace.


 <cfloat>

<cfloat>

namespace std {#include <float.h> };

Include the standard header <cfloat> to effectively include the standard header <float.h> within the std namespace.


 <ciso646>

<ciso646>

namespace std {#include <iso646.h> };

Include the standard header <ciso646> to effectively include the standard header <iso646.h> within the std namespace.


 <climits>

<climits>

namespace std {#include <limits.h> };

Include the standard header <climits> to effectively include the standard header <limits.h> within the std namespace.


 <clocale>

<clocale>

namespace std {#include <locale.h> };

Include the standard header <clocale> to effectively include the standard header <locale.h> within the std namespace.


 <cmath>

<cmath>

namespace std {#include <math.h> };

Include the standard header <cmath> to effectively include the standard header <math.h> within the std namespace.


 <complex>

<complex>

abs · arg · complex · complex<double> · complex<float> · complex<long double> · conjg · cos · cosh · exp · imag · log · log10 · norm · operator!= · operator* · operator+ · operator- · operator/ · operator<< · operator== · operator>> · polar · pow · real · sin · sinh · sqrt · __STD_COMPLEX

namespace std {
#define __STD_COMPLEX
//    TEMPLATE CLASSES
template<class T>
    class complex;
class complex<float>;
class complex<double>;
class complex<long double>;
//    TEMPLATE FUNCTIONS
template<class T>
    complex<T> operator+(const complex<T>& lhs, const complex<T>& rhs);
template<class T>
    complex<T> operator+(const complex<T>& lhs, const T& rhs);
template<class T>
    complex<T> operator+(const T& lhs, const complex<T>& rhs);
template<class T>
    complex<T> operator-(const complex<T>& lhs, const complex<T>& rhs);
template<class T>
    complex<T> operator-(const complex<T>& lhs, const T& rhs);
template<class T>
    complex<T> operator-(const T& lhs, const complex<T>& rhs);
template<class T>
    complex<T> operator*(const complex<T>& lhs, const complex<T>& rhs);
template<class T>
    complex<T> operator*(const complex<T>& lhs, const T& rhs);
template<class T>
    complex<T> operator*(const T& lhs, const complex<T>& rhs);
template<class T>
    complex<T> operator/(const complex<T>& lhs, const complex<T>& rhs);
template<class T>
    complex<T> operator/(const complex<T>& lhs, const T& rhs);
template<class T>
    complex<T> operator/(const T& lhs, const complex<T>& rhs);
template<class T>
    complex<T> operator+(const complex<T>& lhs);
template<class T>
    complex<T> operator-(const complex<T>& lhs);
template<class T>
    bool operator==(const complex<T>& lhs, const complex<T>& rhs);
template<class T>
    bool operator==(const complex<T>& lhs, const T& rhs);
template<class T>
    bool operator==(const T& lhs, const complex<T>& rhs);
template<class T>
    bool operator!=(const complex<T>& lhs, const complex<T>& rhs);
template<class T>
    bool operator!=(const complex<T>& lhs, const T& rhs);
template<class T>
    bool operator!=(const T& lhs, const complex<T>& rhs);
template<class E, class Ti, class T>
    basic_istream<E, Ti>& operator>>(basic_istream<E, Ti>& is,
        complex<T>& x);
template<class E, class T, class U>
    basic_ostream<E, T>& operator<<(basic_ostream<E, T>& os,
        const complex<U>& x);
template<class T>
    T real(const complex<T>& x);
template<class T>
    T imag(const complex<T>& x);
template<class T>
    T abs(const complex<T>& x);
template<class T>
    T arg(const complex<T>& x);
template<class T>
    T norm(const complex<T>& x);
template<class T>
    complex<T> conjg(const complex<T>& x);
template<class T>
    complex<T> polar(const T& rho, const T& theta = 0);
template<class T>
    complex<T> cos(const complex<T>& x);
template<class T>
    complex<T> cosh(const complex<T>& x);
template<class T>
    complex<T> exp(const complex<T>& x);
template<class T>
    complex<T> log(const complex<T>& x);
template<class T>
    complex<T> log10(const complex<T>& x);
template<class T>
    complex<T> pow(const complex<T>& x, int y);
template<class T>
    complex<T> pow(const complex<T>& x, const T& y);
template<class T>
    complex<T> pow(const complex<T>& x, const complex<T>& y);
template<class T>
    complex<T> pow(const T& x, const complex<T>& y);
template<class T>
    complex<T> sin(const complex<T>& x);
template<class T>
    complex<T> sinh(const complex<T>& x);
template<class T>
    complex<T> sqrt(const complex<T>& x);
    };

Include the standard header <complex> to define template class complex and a host of supporting template functions. Unless otherwise specified, functions that can return multiple values return an imaginary part in the half-open interval (-pi, pi].


abs

template<class T>
    T abs(const complex<T>& x);

The function returns the magnitude of x.


arg

template<class T>
    T arg(const complex<T>& x);

The function returns the phase angle of x.


complex

template<class T>
    class complex {
public:
    typedef T value_type;
    T real() const;
    T imag() const;
    complex(const T& re = 0, const T& im = 0);
    complex(const complex& x);
    complex& operator=(const complex& rhs);
    complex& operator+=(const complex& rhs);
    complex& operator-=(const complex& rhs);
    complex& operator*=(const complex& rhs);
    complex& operator/=(const complex& rhs);
    complex& operator=(const T& rhs);
    complex& operator=(const T& rhs);
    complex& operator+=(const T& rhs);
    complex& operator-=(const T& rhs);
    complex& operator*=(const T& rhs);
    complex& operator/=(const T& rhs);
    friend complex<T>
        operator+(const complex<T>& lhs, const T& rhs);
    friend complex<T>
        operator+(const T& lhs, const complex<T>& rhs);
    friend complex<T>
        operator-(const complex<T>& lhs, const T& rhs);
    friend complex<T>
        operator-(const T& lhs, const complex<T>& rhs);
    friend complex<T>
        operator*(const complex<T>& lhs, const T& rhs);
    friend complex<T>
        operator*(const T& lhs, const complex<T>& rhs);
    friend complex<T>
        operator/(const complex<T>& lhs, const T& rhs);
    friend complex<T>
        operator/(const T& lhs, const complex<T>& rhs);
    friend bool operator==(const complex<T>& lhs, const T& rhs);
    friend bool operator==(const T& lhs, const complex<T>& rhs);
    friend bool operator!=(const complex<T>& lhs, const T& rhs);
    friend bool operator!=(const T& lhs, const complex<T>& rhs);
    };

The template class describes an object that stores two objects of type T, one that represents the real part of a complex number and one that represents the imaginary part. An object of class T:

  • Has a public default constructor, destructor, copy constructor, and assignment operator -- with conventional behavior.
  • Can be assigned integer or floating-point values, or type cast to such values -- with conventional behavior.
  • Defines the arithmetic operators defined for the floating-point types -- with conventional behavior.

Explicit specializations of template class complex exist for the three floating-point types. In this implementation, a value of any other type T is type cast to double for actual calculations, with the double result assigned back to the stored object of type T.


complex::complex

complex(const T& re = 0, const T& im = 0);
complex(const complex& x);

The first constructor initializes the stored real part to re and the stored imaginary part to im. The second constructor initializes the stored real part to x.real() and the stored imaginary part to x.imag().

In this implementation, if a translator does not support member template functions, the template:

template<class U>
    complex(const complex<U>& x);

is replaced by:

complex(const complex& x);

which is the copy constructor.


complex::imag

T imag() const;

The member function returns the stored imaginary part.


complex::operator*=

complex& operator*=(const complex& rhs);
complex& operator*=(const T& rhs);

The first member function replaces the stored real and imaginary parts with those corresponding to the complex product of *this and rhs. It then returns *this.

The second member function multiplies both the stored real part and the stored imaginary part with rhs. It then returns *this.

In this implementation, if a translator does not support member template functions, the template:

template<class U>
    complex& operator*=(const complex<U>& rhs);

is replaced by:

complex& operator*=(const complex& rhs);


complex::operator+=

complex& operator+=(const complex& rhs);
complex& operator+=(const T& rhs);

The first member function replaces the stored real and imaginary parts with those corresponding to the complex sum of *this and rhs. It then returns *this.

The second member function adds rhs to the stored real part. It then returns *this.

In this implementation, if a translator does not support member template functions, the template:

template<class U>
    complex& operator+=(const complex<U>& rhs);

is replaced by:

complex& operator+=(const complex& rhs);


complex::operator-=

complex& operator-=(const complex& rhs);
complex& operator-=(const T& rhs);

The first member function replaces the stored real and imaginary parts with those corresponding to the complex difference of *this and rhs. It then returns *this.

The second member function subtracts rhs from the stored real part. It then returns *this.

In this implementation, if a translator does not support member template functions, the template:

template<class U>
    complex& operator-=(const complex<U>& rhs);

is replaced by:

complex& operator-=(const complex& rhs);


complex::operator/=

complex& operator/=(const complex& rhs);
complex& operator/=(const T& rhs);

The first member function replaces the stored real and imaginary parts with those corresponding to the complex quotient of *this and rhs. It then returns *this.

The second member function multiplies both the stored real part and the stored imaginary part with rhs. It then returns *this.

In this implementation, if a translator does not support member template functions, the template:

template<class U>
    complex& operator/=(const complex<U>& rhs);

is replaced by:

complex& operator/=(const complex& rhs);


complex::operator=

complex& operator=(const complex& rhs);
complex& operator=(const T& rhs);

The first member function replaces the stored real part with rhs.real() and the stored imaginary part with rhs.imag(). It then returns *this.

The second member function replaces the stored real part with rhs and the stored imaginary part with zero. It then returns *this.

In this implementation, if a translator does not support member template functions, the template:

template<class U>
    complex& operator=(const complex<U>& rhs);

is replaced by:

complex& operator=(const complex& rhs);

which is the default assignment operator.


complex::real

T real() const;

The member function returns the stored real part.


complex::value_type

typedef T value_type;

The type is a synonym for the template parameter T.


complex<double>

class complex<double> {
public:
    complex(double re = 0, double im = 0);
    complex(const complex<float>& x);
    explicit complex(const complex<long double>& x);
// rest same as template class complex
    };

The explicitly specialized template class describes an object that stores two objects of type double, one that represents the real part of a complex number and one that represents the imaginary part. The explicit specialization differs only in the constructors it defines. The first constructor initializes the stored real part to re and the stored imaginary part to im. The remaining two constructors initialize the stored real part to x.real() and the stored imaginary part to x.imag().


complex<float>

class complex<float> {
public:
    complex(float re = 0, float im = 0);
    explicit complex(const complex<double>& x);
    explicit complex(const complex<long double>& x);
// rest same as template class complex
    };

The explicitly specialized template class describes an object that stores two objects of type float, one that represents the real part of a complex number and one that represents the imaginary part. The explicit specialization differs only in the constructors it defines. The first constructor initializes the stored real part to re and the stored imaginary part to im. The remaining two constructors initialize the stored real part to x.real() and the stored imaginary part to x.imag().


complex<long double>

class complex<long double> {
public:
    complex(long double re = 0, long double im = 0);
    complex(const complex<float>& x);
    complex(const complex<double>& x);
// rest same as template class complex
    };

The explicitly specialized template class describes an object that stores two objects of type long double, one that represents the real part of a complex number and one that represents the imaginary part. The explicit specialization differs only in the constructors it defines. The first constructor initializes the stored real part to re and the stored imaginary part to im. The remaining two constructors initialize the stored real part to x.real() and the stored imaginary part to x.imag().


conjg

template<class T>
    complex<T> conjg(const complex<T>& x);

The function returns the conjugate of x.


cos

template<class T>
    complex<T> cos(const complex<T>& x);

The function returns the cosine of x.


cosh

template<class T>
    complex<T> cosh(const complex<T>& x);

The function returns the hyperbolic cosine of x.


exp

template<class T>
    complex<T> exp(const complex<T>& x);

The function returns the exponential of x.


imag

template<class T>
    T imag(const complex<T>& x);

The function returns the imaginary part of x.


log

template<class T>
    complex<T> log(const complex<T>& x);

The function returns the logarithm of x. The branch cuts are along the negative real axis.


log10

template<class T>
    complex<T> log10(const complex<T>& x);

The function returns the base 10 logarithm of x. The branch cuts are along the negative real axis.


norm

template<class T>
    T norm(const complex<T>& x);

The function returns the squared magnitude of x.


operator!=

template<class T>
    bool operator!=(const complex<T>& lhs, const complex<T>& rhs);
template<class T>
    bool operator!=(const complex<T>& lhs, const T& rhs);
template<class T>
    bool operator!=(const T& lhs, const complex<T>& rhs);

The operators each return true only if real (lhs) != real(rhs) || imag (lhs) != imag(rhs).


operator*

template<class T>
    complex<T> operator*(const complex<T>& lhs, const complex<T>& rhs);
template<class T>
    complex<T> operator*(const complex<T>& lhs, const T& rhs);
template<class T>
    complex<T> operator*(const T& lhs, const complex<T>& rhs);

The operators each convert both operands to the return type, then return the complex product of the converted lhs and rhs.


operator+

template<class T>
    complex<T> operator+(const complex<T>& lhs, const complex<T>& rhs);
template<class T>
    complex<T> operator+(const complex<T>& lhs, const T& rhs);
template<class T>
    complex<T> operator+(const T& lhs, const complex<T>& rhs);
template<class T>
    complex<T> operator+(const complex<T>& lhs);

The binary operators each convert both operands to the return type, then return the complex sum of the converted lhs and rhs.

The unary operator returns lhs.


operator-

template<class T>
    complex<T> operator-(const complex<T>& lhs, const complex<T>& rhs);
template<class T>
    complex<T> operator-(const complex<T>& lhs, const T& rhs);
template<class T>
    complex<T> operator-(const T& lhs, const complex<T>& rhs);
template<class T>
    complex<T> operator-(const complex<T>& lhs);

The binary operators each convert both operands to the return type, then return the complex difference of the converted lhs and rhs.

The unary operator returns a value whose real part is - real (lhs) and whose imaginary part is - imag (lhs).


operator/

template<class T>
    complex<T> operator/(const complex<T>& lhs, const complex<T>& rhs);
template<class T>
    complex<T> operator/(const complex<T>& lhs, const T& rhs);
template<class T>
    complex<T> operator/(const T& lhs, const complex<T>& rhs);

The operators each convert both operands to the return type, then return the complex quotient of the converted lhs and rhs.


operator<<

template<class E, class T, class U>
    basic_ostream<E, T>& operator<<(basic_ostream<E, T>& os,
        const complex<U>& x);

The template function inserts the complex value x into the output stream os, effectively by executing:

basic_ostringstream<E, T> ostr;
ostr.flags(os.flags());
ostr.imbue(os.imbue());
ostr.precision(os.precision());
ostr << '(' << real(x) << ','
    << imag(x) << ')';
os << ostr.str().c_str();

Thus, if os. width () is greater than zero, any padding occurs either before or after the parenthesized pair of values, which itself contains no padding. The function returns os.


operator==

template<class T>
    bool operator==(const complex<T>& lhs, const complex<T>& rhs);
template<class T>
    bool operator==(const complex<T>& lhs, const T& rhs);
template<class T>
    bool operator==(const T& lhs, const complex<T>& rhs);

The operators each return true only if real (lhs) == real(rhs) && imag (lhs) == imag(rhs).


operator>>

template<class E, class T, class U>
    basic_istream<E, T>& operator>>(basic_istream<E, T>& is,
        complex<U>& x);

The template function attempts to extract a complex value from the input stream is, effectively by executing:

is >> ch && ch == '('
    is >> re >> ch && ch == ','
    is >> im >> ch && ch == ')'

Here, ch is an object of type E, and re and im are objects of type U.

If the result of this expression is true, the function stores re in the real part and im in the imaginary part of x. In any event, the function returns is.


polar

template<class T>
    complex<T> polar(const T& rho, const T& theta = 0);

The function returns the complex value whose magnitude is rho and whose phase angle is theta.


pow

template<class T>
    complex<T> pow(const complex<T>& x, int y);
template<class T>
    complex<T> pow(const complex<T>& x, const T& y);
template<class T>
    complex<T> pow(const complex<T>& x, const complex<T>& y);
template<class T>
    complex<T> pow(const T& x, const complex<T>& y);

The functions each effectively convert both operands to the return type, then return the converted x to the power y. The branch cut for x is along the negative real axis.


real

template<class T>
    T real(const complex<T>& x);

The function returns the real part of x.


sin

template<class T>
    complex<T> sin(const complex<T>& x);

The function returns the imaginary sine of x.


sinh

template<class T>
    complex<T> sinh(const complex<T>& x);

The function returns the hyperbolic sine of x.


sqrt

template<class T>
    complex<T> sqrt(const complex<T>& x);

The function returns the square root of x, with phase angle in the half-open interval (-pi/2, pi/2]. The branch cuts are along the negative real axis.


__STD_COMPLEX

#define __STD_COMPLEX

The macro is defined, with an unspecified expansion, to indicate compliance with the specifications of this header.


 <csetjmp>

<csetjmp>

namespace std {
#include <setjmp.h>
    };

Include the standard header<csetjmp> to effectively include the standard header <setjmp.h> within the std namespace.


 <csignal>

<csignal>

namespace std {#include <signal.h> };

Include the standard header <csignal> to effectively include the standard header <signal.h> within the std namespace.


 <cstdarg>

<cstdarg>

namespace std {
#include <stdarg.h>
    };

Include the standard header <cstdarg> to effectively include the standard header <stdarg.h> within the std namespace.


 <cstddef>

<cstddef>

namespace std {#include <stddef.h> };

Include the standard header <cstddef> to effectively include the standard header <stddef.h> within the std namespace.


 <cstdio>

<cstdio>

namespace std {
#include <stdio.h>
     };

Include the standard header <cstdio> to effectively include the standard header <stdio.h> within the std namespace.


 <cstdlib>

<cstdlib>

namespace std {#include <stdlib.h> };

Include the standard header <cstdlib> to effectively include the standard header <stdlib.h> within the std namespace.


 <cstring>

<cstring>

namespace std {#include <string.h> };

Include the standard header <cstring> to effectively include the standard header <string.h> within the std namespace.


 <ctime>

<ctime>

namespace std {#include <time.h> };

Include the standard header <ctime> to effectively include the standard header <time.h> within the std namespace.


 <cwchar>

<cwchar>

namespace std {
#include <wchar.h>
     };

Include the standard header <cwchar> to effectively include the standard header <wchar.h> within the std namespace.


 <cwctype>

<cwctype>

namespace std {#include <wctype.h> };

Include the standard header <cwctype> to effectively include the standard header <wctype.h> within the std namespace.


 <deque>

<deque>

namespace std {
template<class T, class A>
    class deque;
//    TEMPLATE FUNCTIONS
template<class T, class A>
    bool operator==(
        const deque<T, A>& lhs,
        const deque<T, A>& rhs);
template<class T, class A>
    bool operator!=(
        const deque<T, A>& lhs,
        const deque<T, A>& rhs);
template<class T, class A>
    bool operator<(
        const deque<T, A>& lhs,
        const deque<T, A>& rhs);
template<class T, class A>
    bool operator>(
        const deque<T, A>& lhs,
        const deque<T, A>& rhs);
template<class T, class A>
    bool operator<=(
        const deque<T, A>& lhs,
        const deque<T, A>& rhs);
template<class T, class A>
    bool operator>=(
        const deque<T, A>& lhs,
        const deque<T, A>& rhs);
template<class T, class A>
    void swap(
        const deque<T, A>& lhs,
        const deque<T, A>& rhs);
    };

Include the STL standard header <deque> to define the container template class deque and three supporting templates.


deque

allocator_type · assign · at · back · begin · clear · const_iterator · const_reference · const_reverse_iterator · deque · difference_type · empty · end · erase · front · get_allocator · insert · iterator · max_size · operator[] · pop_back · pop_front · push_back · push_front · rbegin · reference · rend · resize · reverse_iterator · size · size_type · swap · value_type

template<class T, class A = allocator<T> >
    class deque {
public:
    typedef A allocator_type;
    typedef A::size_type size_type;
    typedef A::difference_type difference_type;
    typedef A::reference reference;
    typedef A::const_reference const_reference;
    typedef A::value_type value_type;
    typedef T0 iterator;
    typedef T1 const_iterator;
    typedef reverse_iterator<iterator, value_type,
        reference, A::pointer, difference_type>
            reverse_iterator;
    typedef reverse_iterator<const_iterator, value_type,
        const_reference, A::const_pointer, difference_type>
            const_reverse_iterator;
    explicit deque(const A& al = A());
    explicit deque(size_type n, const T& v = T(), const A& al = A());
    deque(const deque& x);
    deque(const_iterator first, const_iterator last,
        const A& al = A());
    iterator begin();
    const_iterator begin() const;
    iterator end();
    iterator end() const;
    reverse_iterator rbegin();
    const_reverse_iterator rbegin() const;
    reverse_iterator rend();
    const_reverse_iterator rend() const;
    void resize(size_type n, T x = T());
    size_type size() const;
    size_type max_size() const;
    bool empty() const;
    A get_allocator() const;
    reference at(size_type pos);
    const_reference at(size_type pos) const;
    reference operator[](size_type pos);
    const_reference operator[](size_type pos);
    reference front();
    const_reference front() const;
    reference back();
    const_reference back() const;
    void push_front(const T& x);
    void pop_front();
    void push_back(const T& x);
    void pop_back();
    void assign(const_iterator first, const_iterator last);
    void assign(size_type n, const T& x = T());
    iterator insert(iterator it, const T& x = T());
    void insert(iterator it, size_type n, const T& x);
    void insert(iterator it,
        const_iterator first, const_iterator last);
    iterator erase(iterator it);
    iterator erase(iterator first, iterator last);
    void clear();
    void swap(deque x);
protected:
    A allocator;
    };

The template class describes an object that controls a varying-length sequence of elements of type T. The sequence is represented in a way that permits insertion and removal of an element at either end with a single element copy (constant time). Such operations in the middle of the sequence require element copies and assignments proportional to the number of elements in the sequence (linear time).

The object allocates and frees storage for the sequence it controls through a protected object named allocator, of class A. Such an allocator object must have the same external interface as an object of template class allocator. Note that allocator is not copied when the object is assigned.

Deque reallocation occurs when a member function must insert or erase elements of the controlled sequence. In all such cases, iterators or references that point anywhere within the controlled sequence become invalid.


deque::allocator_type

typedef A allocator_type;

The type is a synonym for the template parameter A.


deque::assign

void assign(const_iterator first, const_iterator last);
void assign(size_type n, const T& x = T());

The first member function replaces the sequence controlled by *this with the sequence [first, last). The second member function replaces the sequence controlled by *this with a repetition of n elements of value x.

In this implementation, if a translator does not support member template functions, the templates:

template<class InIt>
    void assign(InIt first, InIt last);
template<class Size, class T2>
    void assign(Size n, const T2& x = T2());

are replaced by:

void assign(const_iterator first, const_iterator last);
void assign(size_type n, const T& x = T());

See the related sample program.


deque::at

const_reference at(size_type pos) const;
reference at(size_type pos);

The member function returns a reference to the element of the controlled sequence at position pos. If that position is invalid, the function throws an object of class out_of_range.

See the related sample program.


deque::back

reference back();
const_reference back() const;

The member function returns a reference to the last element of the controlled sequence, which must be non-empty.

See the related sample program.


deque::begin

const_iterator begin() const;
iterator begin();

The member function returns a random-access iterator that points at the first element of the sequence (or just beyond the end of an empty sequence).

See the related sample program.


deque::clear

void clear() const;

The member function calls erase ( begin (), end ()).

See the related sample program.


deque::const_iterator

typedef T1 const_iterator;

The type describes an object that can serve as a constant random-access iterator for the controlled sequence. It is described here as a synonym for the unspecified type T1.


deque::const_reference

typedef A::const_reference const_reference;

The type describes an object that can serve as a constant reference to an element of the controlled sequence.


deque::const_reverse_iterator

typedef reverse_iterator<const_iterator, value_type,
    const_reference, A::const_pointer, difference_type>
        const_reverse_iterator;

The type describes an object that can serve as a constant reverse random-access iterator for the controlled sequence.


deque::deque

explicit deque(const A& al = A());
explicit deque(size_type n, const T& v = T(), const A& al = A());
deque(const deque& x);
deque(const_iterator first, const_iterator last, const A& al = A());

All constructors store the allocator object al (or, for the copy constructor, x. get_allocator ()) in allocator and initialize the controlled sequence. The first constructor specifies an empty initial controlled sequence. The second constructor specifies a repetition of n elements of value x. The third constructor specifies a copy of the sequence controlled by x. The last constructor specifies the sequence [first, last).

In this implementation, if a translator does not support member template functions, the template:

template<class InIt>
    deque(InIt first, InIt last, const A& al = A());

is replaced by:

deque(const_iterator first, const_iterator last, const A& al = A());


deque::difference_type

typedef A::difference_type difference_type;

The signed integer type describes an object that can represent the difference between the addresses of any two elements in the controlled sequence.


deque::empty

bool empty() const;

The member function returns true for an empty controlled sequence.


deque::end

const_iterator end() const;
iterator end();

The member function returns a random-access iterator that points just beyond the end of the sequence.

See the related sample program.


deque::erase

iterator erase(iterator it);
iterator erase(iterator first, iterator last);

The first member function removes the element of the controlled sequence pointed to by it. The second member function removes the elements of the controlled sequence in the range [first, last). Both return an iterator that designates the first element remaining beyond any elements removed, or end () if no such element exists.

Removing N elements causes N destructor calls and an assignment for each of the elements between the insertion point and the nearer end of the sequence. Removing an element at either end invalidates only iterators and references that designate the erased elements. Otherwise, erasing an element invalidates all iterators and references.

See the related sample program.


deque::front

reference front();
const_reference front() const;

The member function returns a reference to the first element of the controlled sequence, which must be non-empty.

See the related sample program.


deque::get_allocator

A get_allocator() const;

The member function returns allocator.


deque::insert

iterator insert(iterator it, const T& x = T());
void insert(iterator it, size_type n, const T& x);
void insert(iterator it, const_iterator first, const_iterator last);

Each of the member functions inserts, before the element pointed to by it in the controlled sequence, a sequence specified by the remaining operands. The first member function inserts a single element with value x and returns an iterator that points to the newly inserted element. The second member function inserts a repetition of n elements of value x. The last member function inserts the sequence [first, last).

In this implementation, if a translator does not support member template functions, the template:

template<class InIt>
    void insert(iterator it, InIt first, InIt last);

is replaced by:

void insert(iterator it, const_iterator first, const_iterator last);

When inserting a single element, the number of element copies is linear in the number of elements between the insertion point and the nearer end of the sequence. When inserting a single element at either end of the sequence, the amortized number of element copies is constant. When inserting N elements, the number of element copies is linear in N plus the number of elements between the insertion point and the nearer end of the sequence -- except when the template member is specialized for InIt an input or forward iterator, which behaves like N single insertions. Inserting an element at either end invalidates all iterators, but no references, that designate existing elements. Otherwise, inserting an element invalidates all iterators and references.

See the related sample program.


deque::iterator

typedef T0 iterator;

The type describes an object that can serve as a random-access iterator for the controlled sequence. It is described here as a synonym for the unspecified type T0.


deque::max_size

size_type max_size() const;

The member function returns the length of the longest sequence that the object can control.


deque::operator[]

const_reference operator[](size_type pos) const;
reference operator[](size_type pos);

The member function returns a reference to the element of the controlled sequence at position pos. If that position is invalid, the behavior is undefined.

See the related sample program.


deque::pop_back

void pop_back();

The member function removes the last element of the controlled sequence, which must be non-empty. Removing the element invalidates only iterators and references that designate the erased element.

See the related sample program.


deque::pop_front

void pop_front();

The member function removes the first element of the controlled sequence, which must be non-empty. Removing the element invalidates only iterators and references that designate the erased element.

See the related sample program.


deque::push_back

void push_back(const T& x);

The member function inserts an element with value x at the end of the controlled sequence. Inserting the element invalidates all iterators, but no references, to existing elements.

See the related sample program.


deque::push_front

void push_front(const T& x);

The member function inserts an element with value x at the beginning of the controlled sequence. Inserting the element invalidates all iterators, but no references, to existing elements.

See the related sample program.


deque::rbegin

const_reverse_iterator rbegin() const;
reverse_iterator rbegin();

The member function returns a reverse iterator that points just beyond the end of the controlled sequence. Hence, it designates the beginning of the reverse sequence.

See the related sample program.


deque::reference

typedef A::reference reference;

The type describes an object that can serve as a reference to an element of the controlled sequence.


deque::rend

const_reverse_iterator rend() const;
reverse_iterator rend();

The member function returns a reverse iterator that points at the first element of the sequence (or just beyond the end of an empty sequence). Hence, it designates the end of the reverse sequence.

See the related sample program.


deque::resize

void resize(size_type n, T x = T());

The member function ensures that size () henceforth returns n. If it must lengthen the controlled sequence, it appends elements with value x.

See the related sample program.


deque::reverse_iterator

typedef reverse_iterator<iterator, value_type,
    reference, A::pointer, difference_type>
        reverse_iterator;

The type describes an object that can serve as a reverse random-access iterator for the controlled sequence.


deque::size

size_type size() const;

The member function returns the length of the controlled sequence.

See the related sample program.


deque::size_type

typedef A::size_type size_type;

The unsigned integer type describes an object that can represent the length of any controlled sequence.


deque::swap

void swap(deque& str);

The member function swaps the controlled sequences between *this and str. If allocator == str.allocator, it does so in constant time. Otherwise, it performs a number of element assignments and constructor calls proportional to the number of elements in the two controlled sequences.

See the related sample program.


deque::value_type

typedef A::value_type value_type;

The type is a synonym for the template parameter T.


operator!=

template<class T, class A>
    bool operator!=(
        const deque <T, A>& lhs,
        const deque <T, A>& rhs);

The template function returns !(lhs == rhs).


operator==

template<class T, class A>
    bool operator==(
        const deque <T, A>& lhs,
        const deque <T, A>& rhs);

The template function overloads operator== to compare two objects of template class deque. The function returns lhs. size () == rhs.size() && equal (lhs. begin (), lhs. end (), rhs.begin()).

See the related sample program.


operator<

template<class T, class A>
    bool operator<(
        const deque <T, A>& lhs,
        const deque <T, A>& rhs);

The template function overloads operator< to compare two objects of template class deque. The function returns lexicographical_compare (lhs. begin (), lhs. end (), rhs.begin(), rhs.end()).

See the related sample program.


operator<=

template<class T, class A>
    bool operator<=(
        const deque <T, A>& lhs,
        const deque <T, A>& rhs);

The template function returns !(rhs < lhs).


operator>

template<class T, class A>
    bool operator>(
        const deque <T, A>& lhs,
        const deque <T, A>& rhs);

The template function returns rhs < lhs.


operator>=

template<class T, class A>
    bool operator>=(
        const deque <T, A>& lhs,
        const deque <T, A>& rhs);

The template function returns !(rhs < lhs).


swap

template<class T, class A>
    void swap(
        const deque <T, A>& lhs,
        const deque <T, A>& rhs);

The template function executes lhs. swap (rhs).


 <exception>

<exception>

namespace std {
    class exception;
    class bad_exception;
    typedef void (*terminate_handler)();
    typedef void (*unexpected_handler)();
    terminate_handler set_terminate(terminate_handler ph) throw();
    unexpected_handler set_unexpected(unexpected_handler ph) throw();
    void terminate();
    void unexpected();
    bool uncaught_exception();
    };

Include the standard header <exception> to define several types and functions related to the handling of exceptions.


bad_exception

class bad_exception : public exception {
    };

The class describes an exception that can be thrown from an unexpected handler. The value returned by what () is implementation-defined. None of the member functions throw any exceptions.


exception

class exception {
public:
    exception() throw();
    exception(const exception& rhs) throw();
    exception& operator=(const exception& rhs) throw();
    virtual ~exception() throw();
    virtual const char *what() const throw();
    };

The class serves as the base class for all exceptions thrown by certain expressions and by the Standard C++ library. The C string value returned by what() is left unspecified by the default constructor, but may be defined by the constructors for certain derived classes. None of the member functions throw any exceptions.


set_terminate

terminate_handler set_terminate(terminate_handler ph) throw();

The function establishes a new terminate handler as the function *ph. Thus, ph must not be a null pointer. The function returns the address of the previous terminate handler.


set_unexpected

unexpected_handler set_unexpected(unexpected_handler ph) throw();

The function establishes a new unexpected handler as the function *ph. Thus, ph must not be a null pointer. The function returns the address of the previous unexpected handler.


terminate_handler

typedef void (*terminate_handler)();

The type describes a pointer to a function suitable for use as a terminate handler.


unexpected_handler

typedef void (*unexpected_handler)();

The type describes a pointer to a function suitable for use as an unexpected handler.


terminate

void terminate();

The function calls the current terminate handler, a function of type void () called when exception handling must be abandoned for any of several reasons. A terminate handler may not return to its caller. At program startup, the terminate handler is a function that calls abort().


uncaught_exception

bool uncaught_exception();

The function returns true only if a thrown exception is being currently processed.


unexpected

void unexpected();

The function calls the current unexpected handler, a function of type void () called when control leaves a function by a thrown exception of a type not permitted by an exception specification for the function, as in:

void f() throw()      // function may throw no exceptions
    {throw "bad"; }   // unexpected throw calls unexpected()

An unexpected handler may not return to its caller. It may terminate execution by:

  • Throwing an object of a type listed in the exception specification.
  • Throwing an object of type bad_exception.
  • Calling terminate (), abort(), or exit(int).

At program startup, the unexpected handler is a function that calls terminate ().


 <fstream>

<fstream>

namespace std {
    template<class E, class T = char_traits<E> >
        class basic_filebuf;
    typedef basic_filebuf<char> filebuf;
    typedef basic_filebuf<wchar_t> wfilebuf;
    template<class E, class T = char_traits<E> >
        class basic_ifstream;
    typedef basic_ifstream<char> ifstream;
    typedef basic_ifstream<wchar_t> wifstream;
    template<class E, class T = char_traits<E> >
        class basic_ofstream;
    typedef basic_ofstream<char> ofstream;
    typedef basic_ofstream<wchar_t> wofstream;
    template<class E, class T = char_traits<E> >
        class basic_fstream;
    typedef basic_fstream<char> fstream;
    typedef basic_fstream<wchar_t> wfstream;
    };

Include the iostreams standard header <fstream> to define several template classes that support iostreams operations on sequences stored in external files.


basic_filebuf

template <class E, class T = char_traits<E> >
    class basic_filebuf : public basic_streambuf<E, T> {
public:
    basic_filebuf();
    bool is_open() const;
    basic_filebuf *open(const char *s, ios_base::openmode mode);
    basic_filebuf *close();
protected:
    virtual pos_type seekoff(off_type off, ios_base::seekdir way,
        ios_base::openmode which = ios_base::in | ios_base::out);
    virtual pos_type seekpos(pos_type pos,
        ios_base::openmode which = ios_base::in | ios_base::out);
    virtual int_type underflow();
    virtual int_type pbackfail(int_type c = T::eof());
    virtual int_type overflow(int_type c = T::eof());
    virtual int sync();
    virtual basic_streambuf<E, T> *setbuf(E *s, streamsize n);
    };

The template class describes a stream buffer that controls the transmission of elements to and from a sequence of elements stored in an external file.

An object of class basic_filebuf<E, T> stores a file pointer, which designates the FILE object that controls the stream associated with an open file. It also stores pointers to two file conversion facets for use by the protected member functions overflow and underflow.


basic_filebuf::basic_filebuf

basic_filebuf();

The constructor stores a null pointer in all the pointers controlling the input buffer and the output buffer. It also stores a null pointer in the file pointer.


basic_filebuf::close

basic_filebuf *close();

The member function returns a null pointer if the file pointer fp is a null pointer. Otherwise, it calls fclose(fp). If that function returns a nonzero value, the function returns a null pointer. Otherwise, it returns this to indicate that the file was successfully closed.


basic_filebuf::is_open

bool is_open();

The member function returns true if the file pointer is not a null pointer.


basic_filebuf::open

basic_filebuf *open(const char *s, ios_base::openmode mode);

The member function endeavors to open the file with file name s, by calling fopen(s, strmode). Here strmode is determined from mode & ~( ate & | binary ):

  • ios_base:: in becomes "r" (open existing file for reading).
  • ios_base:: out or
  • ios_base::out | ios_base:: trunc becomes "w" (truncate existing file or create for writing).
  • ios_base::out | app becomes "a" (open existing file for appending all writes).
  • ios_base::in | ios_base::out becomes "r+" (open existing file for reading and writing).
  • ios_base::in | ios_base::out | ios_base::trunc becomes "w+" (truncate existing file or create for reading and writing).
  • ios_base::in | ios_base::out | ios_base::app becomes "a+" (open existing file for reading and for appending all writes).

If mode & ios_base::binary is nonzero, the function appends b to strmode to open a binary stream instead of a text stream. It then stores the value returned by fopen in the file pointer fp. If mode & ios_base::ate is nonzero and the file pointer is not a null pointer, the function calls fseek(fp, 0, SEEK_END) to position the stream at end-of-file. If that positioning operation fails, the function calls close (fp) and stores a null pointer in the file pointer.

If the file pointer is not a null pointer, the function determines the file conversion facet use_facet < codecvt <E, char, T:: state_type > >( getloc ()), for use by underflow and overflow.

If the file pointer is a null pointer, the function returns a null pointer. Otherwise, it returns this.


basic_filebuf::overflow

virtual int_type overflow(int_type c = T::eof());

If c != T:: eof (), the protected virtual member function endeavors to insert the element T:: to_char_type (c) into the output buffer. It can do so in various ways:

  • If a write position is available, it can store the element into the write position and increment the next pointer for the output buffer.
  • It can make a write position available by allocating new or additional storage for the output buffer.
  • It can convert any pending output in the output buffer, followed by c, by using the file conversion facet fac to call fac. out as needed. Each element x of type char thus produced is written to the associated stream designated by the file pointer fp as if by successive calls of the form fputc(x, fp). If any conversion or write fails, the function does not succeed.

If the function cannot succeed, it returns T::eof(). Otherwise, it returns T:: not_eof (c).


basic_filebuf::pbackfail

virtual int_type pbackfail(int_type c = T::eof());

The protected virtual member function endeavors to put back an element into the input buffer, then make it the current element (pointed to by the next pointer). If c == T:: eof (), the element to push back is effectively the one already in the stream before the current element. Otherwise, that element is replaced by x = T:: to_char_type (c). The function can put back an element in various ways:

  • If a putback position is available, and the element stored there compares equal to x, it can simply decrement the next pointer for the input buffer.
  • If the function can make a putback position available, it can do so, set the next pointer to point at that position, and store x in that position.
  • If the function can push back an element onto the input stream, it can do so, such as by calling ungetc for an element of type char.

If the function cannot succeed, it returns T::eof(). Otherwise, it returns T:: not_eof (c).


basic_filebuf::seekoff

virtual pos_type seekoff(off_type off, ios_base::seekdir way,
    ios_base::openmode which = ios_base::in | ios_base::out);

The protected virtual member function endeavors to alter the current positions for the controlled streams. For an object of class basic_filebuf<E, T>, a stream position can be represented by an object of type fpos_t, which stores an offset and any state information needed to parse a wide stream. Offset zero designates the first element of the stream. (An object of type pos_type stores at least an fpos_t object.)

For a file opened for both reading and writing, both the input and output streams are positioned in tandem. To switch between inserting and extracting, you must call either pubseekoff or pubseekpos. Calls to pubseekoff (and hence to seekoff) have various limitations for text streams, binary streams, and wide streams.

If the file pointer fp is a null pointer, the function fails. Otherwise, it endeavors to alter the stream position by calling fseek(fp, off, way). If that function succeeds and the resultant position fposn can be determined by calling fgetpos(fp, &fposn), the function succeeds. If the function succeeds, it returns a value of type pos_type containing fposn. Otherwise, it returns an invalid stream position.


basic_filebuf::seekpos

virtual pos_type seekpos(pos_type pos,
    ios_base::openmode which = ios_base::in | ios_base::out);

The protected virtual member function endeavors to alter the current positions for the controlled streams. For an object of class basic_filebuf<E, T>, a stream position can be represented by an object of type fpos_t, which stores an offset and any state information needed to parse a wide stream. Offset zero designates the first element of the stream. (An object of type pos_type stores at least an fpos_t object.)

For a file opened for both reading and writing, both the input and output streams are positioned in tandem. To switch between inserting and extracting, you must call either pubseekoff or pubseekpos. Calls to pubseekoff (and hence to seekoff) have various limitations for text streams, binary streams, and wide streams.

If the file pointer fp is a null pointer, the function fails. Otherwise, it endeavors to alter the stream position by calling fsetpos(fp, &fposn), where fposn is the fpos_t object stored in pos. If that function succeeds, the function returns pos. Otherwise, it returns an invalid stream position.


basic_filebuf::setbuf

virtual basic_streambuf<E, T> *setbuf(E *s, streamsize n);

The protected member function returns zero if the file pointer fp is a null pointer. Otherwise, it calls setvbuf(fp, (char *)s, _IOFBF, n * sizeof (E)) to offer the array of n elements beginning at s as a buffer for the stream. If that function returns a nonzero value, the function returns a null pointer. Otherwise, it returns this to signal success.


basic_filebuf::sync

int sync();

The protected member function returns zero if the file pointer fp is a null pointer. Otherwise, it returns fflush(fp) to flush any pending output to the stream.


basic_filebuf::underflow

virtual int_type underflow();

The protected virtual member function endeavors to extract the current element c from the input stream, and return the element as T:: to_int_type (c). It can do so in various ways:

  • If a read position is available, it takes c as the element stored in the read position and advances the next pointer for the input buffer.
  • It can read one or more elements of type char, as if by successive calls of the form fgetc(fp), and convert them to an element c of type E by using the file conversion facet fac to call fac. in as needed. If any read or conversion fails, the function does not succeed.

If the function cannot succeed, it returns T:: eof (). Otherwise, it returns c, converted as described above.


basic_fstream

template <class E, class T = char_traits<E> >
    class basic_fstream : public basic_iostream<E, T> {
public:
    explicit basic_fstream();
    explicit basic_fstream(const char *s,
        ios_base::openmode mode = ios_base::in | ios_base::out);
    basic_filebuf<E, T> *rdbuf() const;
    bool is_open() const;
    void open(const char *s,
        ios_base::openmode mode = ios_base::in | ios_base::out);
    void close();
    };

The template class describes an object that controls insertion and extraction of elements and encoded objects using a stream buffer of class basic_filebuf <E, T>, with elements of type E, whose character traits are determined by the class T. The object stores an object of class basic_filebuf<E, T>.


basic_fstream::basic_fstream

explicit basic_fstream();
explicit basic_fstream(const char *s,
    ios_base::openmode mode = ios_base::in | ios_base::out);

The first constructor initializes the base class by calling basic_iostream (sb), where sb is the stored object of class basic_filebuf <E, T>. It also initializes sb by calling basic_filebuf <E, T>().

The second constructor initializes the base class by calling basic_iostream(sb). It also initializes sb by calling basic_filebuf <E, T>(), then sb. open (s, mode). If the latter function returns a null pointer, the constructor calls setstate (failbit).


basic_fstream::close

 voidclose();

The member function calls rdbuf ()-> close ().


basic_fstream::is_open

bool is_open();

The member function returns rdbuf ()-> is_open ().


basic_fstream::open

void open(const char *s,
    ios_base::openmode mode = ios_base::in | ios_base::out);

The member function calls rdbuf ()-> open (s, mode). If that function returns a null pointer, the function calls setstate (failbit).


basic_fstream::rdbuf

basic_filebuf<E, T> *rdbuf() const

The member function returns the address of the stored stream buffer, of type pointer to basic_filebuf <E, T>.


basic_ifstream

template <class E, class T = char_traits<E> >
    class basic_ifstream : public basic_istream<E, T> {
public:
    explicit basic_ifstream();
    explicit basic_ifstream(const char *s,
        ios_base::openmode mode = ios_base::in);
    basic_filebuf<E, T> *rdbuf() const;
    bool is_open() const;
    void open(const char *s,
        ios_base::openmode mode = ios_base::in);
    void close();
    };

The template class describes an object that controls extraction of elements and encoded objects from a stream buffer of class basic_filebuf <E, T>, with elements of type E, whose character traits are determined by the class T. The object stores an object of class basic_filebuf<E, T>.


basic_ifstream::basic_ifstream

explicit basic_ifstream();
explicit basic_ifstream(const char *s,
    ios_base::openmode mode = ios_base::in);

The first constructor initializes the base class by calling basic_istream (sb), where sb is the stored object of class basic_filebuf <E, T>. It also initializes sb by calling basic_filebuf <E, T>().

The second constructor initializes the base class by calling basic_istream(sb). It also initializes sb by calling basic_filebuf <E, T>(), then sb. open (s, mode | ios_base::in). If the latter function returns a null pointer, the constructor calls setstate (failbit).


basic_ifstream::close

void close();

The member function calls rdbuf ()-> close ().


basic_ifstream::is_open

bool is_open();

The member function returns rdbuf ()-> is_open ().


basic_ifstream::open

void open(const char *s,
    ios_base::openmode mode = ios_base::in);

The member function calls rdbuf ()-> open (s, mode | ios_base::in). If that function returns a null pointer, the function calls setstate (failbit).


basic_ifstream::rdbuf

basic_filebuf<E, T> *rdbuf() const

The member function returns the address of the stored stream buffer, of type pointer to basic_filebuf <E, T>.


basic_ofstream

template <class E, class T = char_traits<E> >
    class basic_ofstream : public basic_ostream<E, T> {
public:
    explicit basic_ofstream();
    explicit basic_ofstream(const char *s,
        ios_base::openmode mode = ios_base::out | ios_base::trunc);
    basic_filebuf<E, T> *rdbuf() const;
    bool is_open() const;
    void open(const char *s,
        ios_base::openmode mode = ios_base::out | ios_base::trunc);
    void close();
    };

The template class describes an object that controls insertion of elements and encoded objects into a stream buffer of class basic_filebuf <E, T>, with elements of type E, whose character traits are determined by the class T. The object stores an object of class basic_filebuf<E, T>.


basic_ofstream::basic_ofstream

explicit basic_ofstream();
explicit basic_ofstream(const char *s,
    ios_base::openmode which = ios_base::out | ios_base::trunc);

The first constructor initializes the base class by calling basic_ostream (sb), where sb is the stored object of class basic_filebuf <E, T>. It also initializes sb by calling basic_filebuf <E, T>().

The second constructor initializes the base class by calling basic_ostream(sb). It also initializes sb by calling basic_filebuf <E, T>(), then sb. open (s, mode | ios_base::out). If the latter function returns a null pointer, the constructor calls setstate (failbit).


basic_ofstream::close

void close();

The member function calls rdbuf ()-> close ().


basic_ofstream::is_open

bool is_open();

The member function returns rdbuf ()-> is_open ().


basic_ofstream::open

void open(const char *s,
    ios_base::openmode mode = ios_base::out | ios_base::trunc);

The member function calls rdbuf ()-> open (s, mode | ios_base::out). If that function returns a null pointer, the function calls setstate (failbit).


basic_ofstream::rdbuf

basic_filebuf<E, T> *rdbuf() const

The member function returns the address of the stored stream buffer, of type pointer to basic_filebuf <E, T>.


filebuf

typedef basic_filebuf<char, char_traits<char> > filebuf;

The type is a synonym for template class basic_filebuf, specialized for elements of type char with default character traits.


fstream

typedef basic_fstream<char, char_traits<char> > fstream;

The type is a synonym for template class basic_fstream, specialized for elements of type char with default character traits.


ifstream

typedef basic_ifstream<char, char_traits<char> > ifstream;

The type is a synonym for template class basic_ifstream, specialized for elements of type char with default character traits.


ofstream

typedef basic_ofstream<char, char_traits<char> > ofstream;

The type is a synonym for template class basic_ofstream, specialized for elements of type char with default character traits.


wfilebuf

typedef basic_filebuf<wchar_t, char_traits<wchar_t> > wfilebuf;

The type is a synonym for template class basic_filebuf, specialized for elements of type wchar_t with default character traits.


wfstream

typedef basic_fstream<wchar_t, char_traits<wchar_t> > wfstream;

The type is a synonym for template class basic_fstream, specialized for elements of type wchar_t with default character traits.


wifstream

typedef basic_ifstream<wchar_t, char_traits<wchar_t> > wifstream;

The type is a synonym for template class basic_ifstream, specialized for elements of type wchar_t with default character traits.


wofstream

typedef basic_ofstream<wchar_t, char_traits<wchar_t> > wofstream;

The type is a synonym for template class basic_ofstream, specialized for elements of type wchar_t with default character traits.


 <functional>

<functional>

binary_function · binary_negate · binder1st · binder2nd · divides · equal_to · greater · greater_equal · less · less_equal · logical_and · logical_not · logical_or · mem_fun_t · mem_fun_ref_t · mem_fun1 · mem_fun1_ref_t · minus · modulus · multiplies · negate · not_equal_to · plus · pointer_to_binary_function · pointer_to_unary_function · unary_function · unary_negate

bind1st · bind2nd · mem_fun · mem_fun_ref · mem_fun1 · mem_fun1_ref · not1 · not2 · ptr_fun

namespace std {
//  TEMPLATE CLASSES
template<class Arg, class Result>
    struct unary_function;
template<class Arg1, class Arg2, class Result>
    struct binary_function;
template<class T>
    struct plus;
template<class T>
    struct minus;
template<class T>
    struct multiplies;
template<class T>
    struct divides;
template<class T>
    struct modulus;
template<class T>
    struct negate;
template<class T>
    struct equal_to;
template<class T>
    struct not_equal_to;
template<class T>
    struct greater;
template<class T>
    struct less;
template<class T>
    struct greater_equal;
template<class T>
    struct less_equal;
template<class T>
    struct logical_and;
template<class T>
    struct logical_or;
template<class T>
    struct logical_not;
template<class Pred>
    struct unary_negate;
template<class Pred>
    struct binary_negate;
template<class Pred>
    class binder1st;
template<class Pred>
    class binder2nd;
template<class Arg, class Result>
    class pointer_to_unary_function;
template<class Arg1, class Arg2, class Result>
    class pointer_to_binary_function;
template<class R, class T>
    struct mem_fun_t;
template<class R, class T, class A>
    struct mem_fun1_t;
template<class R, class T>
    struct mem_fun_ref_t;
template<class R, class T, class A>
    struct mem_fun1_ref_t;
//  TEMPLATE FUNCTIONS
template<class Pred>
    unary_negate<Pred> not1(const Pred& pr);
template<class Pred>
    binary_negate<Pred> not2(const Pred& pr);
template<class Pred, class T>
    binder1st<Pred> bind1st(const Pred& pr, const T& x);
template<class Pred, class T>
    binder2nd<Pred> bind2nd(const Pred& pr, const T& x);
template<class Arg, class Result>
    pointer_to_unary_function<Arg, Result>
        ptr_fun(Result (*)(Arg));
template<class Arg1, class Arg2, class Result>
    pointer_to_binary_function<Arg1, Arg2, Result>
        ptr_fun(Result (*)(Arg1, Arg2));
template<class R, class T>
    mem_fun_t<R, T> mem_fun(R (T::*pm)());
template<class R, class T, class A>
    mem_fun1_t<R, T, A> mem_fun1(R (T::*pm)(A arg));
template<class R, class T>
    mem_fun_ref_t<R, T> mem_fun_ref(R (T::*pm)());
template<class R, class T, class A>
    mem_fun1_ref_t<R, T, A> mem_fun1_ref(R (T::*pm)(A arg));
    };

Include the STL standard header <functional> to define several templates that help construct function objects, objects of a class that defines operator(). Hence, function objects behave much like function pointers, except that the object can store additional information that can be used during a function call.


binary_function

template<class Arg1, class Arg2, class Result>
    struct binary_function {
    typedef Arg1 first_argument_type;
    typedef Arg2 second_argument_type;
    typedef Result result_type;
    };

The template class serves as a base for classes that define a member function of the form:

result_type operator()(first_argument_type, second_argument_type)

Hence, all such binary functions can refer to their first argument type as first_argument_type, their second argument type as second_argument_type, and their return type as result_type.

See the related sample program.


binary_negate

template<class Pred>
    class binary_negate
        : public binary_function<Pred::first_argument_type,
            Pred::second_argument_type, bool> {
public:
    explicit binary_negate(const Pred& pr);
    bool operator()(const first_argument_type& x,
        const second_argument_type& y) const;
    };

The template class stores a copy of pr, which must be a binary function object. It defines its member function operator() as returning !pr(x, y).


bind1st

template<class Pred, class T>
    binder1st<Pred> bind1st(const Pred& pr, const T& x);

The function returns binder1st <Pred>(pr, Pred::first_argument_type(x)).


bind2nd

template<class Pred, class T>
    binder2nd<Pred> bind2nd(const Pred& pr, const T& y);

The function returns binder2nd <Pred>(pr, Pred::second_argument_type(y)).


binder1st

template<class Pred>
    class binder1st
        : public unary_function<Pred::second_argument_type,
            Pred::result_type> {
public:
    binder1st(const Pred& pr, const Pred::first_argument_type x);
    result_type operator()(const argument_type& y) const;
protected:
    Pred op;
    Pred::first_argument_type value;
    };

The template class stores a copy of pr, which must be a binary function object, in op, and a copy of x in value. It defines its member function operator() as returning op(value, y).


binder2nd

template<class Pred>
    class binder2nd
        : public unary_function<Pred::first_argument_type,
            Pred::result_type> {
public:
    binder2nd(const Pred& pr, const Pred::second_argument_type y);
    result_type operator()(const argument_type& x) const;
protected:
    Pred op;
    Pred::second_argument_type value;
    };

The template class stores a copy of pr, which must be a binary function object, in op, and a copy of y in value. It defines its member function operator() as returning op(x, value).


divides

template<class T>
    struct divides : public binary_function<T, T, T> {
    T operator()(const T& x, const T& y) const;
    };

The template class defines its member function as returning x / y.

See the related sample program.


equal_to

template<class T>
    struct equal_to : public binary_function<T, T, bool> {
    bool operator()(const T& x, const T& y) const;
    };

The template class defines its member function as returning x == y.


greater

template<class T>
    struct greater : public binary_function<T, T, bool> {
    bool operator()(const T& x, const T& y) const;
    };

The template class defines its member function as returning x > y. The member function defines a total ordering, even if T is an object pointer type.


greater_equal

template<class T>
    struct greater_equal : public binary_function<T, T, bool> {
    bool operator()(const T& x, const T& y) const;
    };

The template class defines its member function as returning x >= y. The member function defines a total ordering, even if T is an object pointer type.


less

template<class T>
    struct less : public binary_function<T, T, bool> {
    bool operator()(const T& x, const T& y) const;
    };

The template class defines its member function as returning x < y. The member function defines a total ordering, even if T is an object pointer type.


less_equal

template<class T>
    struct less_equal : public binary_function<T, T, bool> {
    bool operator()(const T& x, const T& y) const;
    };

The template class defines its member function as returning x <= y. The member function defines a total ordering, even if T is an object pointer type.


logical_and

template<class T>
    struct logical_and : public binary_function<T, T, bool> {
    bool operator()(const T& x, const T& y) const;
    };

The template class defines its member function as returning x && y.


logical_not

template<class T>
    struct logical_not : public unary_function<T, bool> {
    bool operator()(const T& x) const;
    };

The template class defines its member function as returning !x.


logical_or

template<class T>
    struct logical_or : public binary_function<T, T, bool> {
    bool operator()(const T& x, const T& y) const;
    };

The template class defines its member function as returning x || y.


mem_fun

template<class R, class T>
    mem_fun_t<R, T> mem_fun(R (T::*pm)());

The template function returns mem_fun_t <R, T>(pm).


mem_fun_ref

template<class R, class T>
    mem_fun_ref_t<R, T> mem_fun_ref(R (T::*pm)());

The template function returns mem_fun_ref_t <R, T>(pm).


mem_fun_ref_t

template<class R, class T>
    struct mem_fun_ref_t : public unary_function<T *, R> {
    explicit mem_fun_t(R (T::*pm)());
    R operator()(T& x);
    };

The template class stores a copy of pm, which must be a pointer to a member function of class T, in a private member object. It defines its member function operator() as returning (x.*Pm)().


mem_fun_t

template<class R, class T>
    struct mem_fun_t : public unary_function<T *, R> {
    explicit mem_fun_t(R (T::*pm)());
    R operator()(T *p);
    };

The template class stores a copy of pm, which must be a pointer to a member function of class T, in a private member object. It defines its member function operator() as returning (p->*pm)().


mem_fun1

template<class R, class T, class A>
    mem_fun1_t<R, T, A> mem_fun1(R (T::*pm)(A));

The template function returns mem_fun1_t <R, T, A>(pm).


mem_fun1_ref

template<class R, class T, class A>
    mem_fun1_ref_t<R, T, A> mem_fun1_ref(R (T::*pm)(A));

The template function returns mem_fun1_ref_t <R, T, A>(pm).


mem_fun1_ref_t

template<class R, class T, class A>
    struct mem_fun1_ref_t : public binary_function<T *, A, R> {
    explicit mem_fun1_ref_t(R (T::*pm)(A));
    R operator()(T& x, A arg);
    };

The template class stores a copy of pm, which must be a pointer to a member function of class T, in a private member object. It defines its member function operator() as returning (x.*pm)(arg).


mem_fun1_t

template<class R, class T, class A>
    struct mem_fun1_t : public binary_function<T *, A, R> {
    explicit mem_fun1_t(R (T::*pm)(A));
    R operator()(T *p, A arg);
    };

The template class stores a copy of pm, which must be a pointer to a member function of class T, in a private member object. It defines its member function operator() as returning (p->*pm)(arg).


minus

template<class T>
    struct minus : public binary_function<T, T, T> {
    T operator()(const T& x, const T& y) const;
    };

The template class defines its member function as returning x - y.

See the related sample program.


modulus

template<class T>
    struct modulus : public binary_function<T, T, T> {
    T operator()(const T& x, const T& y) const;
    };

The template class defines its member function as returning x % y.

See the related sample program.


multiplies

template<class T>
    struct multiplies : public binary_function<T, T, T> {
    T operator()(const T& x, const T& y) const;
    };

The template class defines its member function as returning x * y.

See the related sample program.


negate

template<class T>
    struct negate : public unary_function<T, T> {
    T operator()(const T& x) const;
    };

The template class defines its member function as returning -x.


not1

template<class Pred>
    unary_negate<Pred> not1(const Pred& pr);

The template function returns unary_negate <Pred>(pr).


not2

template<class Pred>
    binary_negate<Pred> not2(const Pred& pr);

The template function returns binary_negate <Pred>(pr).


not_equal_to

template<class T>
    struct not_equal_to : public binary_function<T, T, bool> {
    bool operator()(const T& x, const T& y) const;
    };

The template class defines its member function as returning x != y.


plus

template<class T>
    struct plus : public binary_function<T, T, T> {
    T operator()(const T& x, const T& y) const;
    };

The template class defines its member function as returning x + y.

See the related sample program.


pointer_to_binary_function

template<class Arg1, class Arg2, class Result>
    class pointer_to_binary_function
        : public binary_function<Arg1, Arg2, Result> {
public:
    explicit pointer_to_binary_function(Result (*pf)(Arg1, Arg2));
    Result operator()(const Arg1 x, const Arg2 y) const;
    };

The template class stores a copy of pf. It defines its member function operator() as returning (*pf)(x, y).


pointer_to_unary_function

template<class Arg, class Result>
    class pointer_to_unary_function
        : public unary_function<Arg, Result> {
public:
    explicit pointer_to_unary_function(Result (*pf)(Arg));
    Result operator()(const Arg x) const;
    };

The template class stores a copy of pf. It defines its member function operator() as returning (*pf)(x).


ptr_fun

template<class Arg, class Result>
    pointer_to_unary_function<Arg, Result>
        ptr_fun(Result (*pf)(Arg));
template<class Arg1, class Arg2, class Result>
    pointer_to_binary_function<Arg1, Arg2, Result>
        ptr_fun(Result (*pf)(Arg1, Arg2));

The first template function returns pointer_to_unary_function <Arg, Result>(pf).

The second template function returns pointer_to_binary_function <Arg1, Arg2, Result>(pf).


unary_function

template<class Arg, class Result>
    struct unary_function {
    typedef Arg argument_type;
    typedef Result result_type;
    };

The template class serves as a base for classes that define a member function of the form:

result_type operator()(argument_type)

Hence, all such unary functions can refer to their sole argument type as argument_type and their return type as result_type.

See the related sample program.


unary_negate

template<class Pred>
    class unary_negate
        : public unary_function<Pred::argument_type, bool> {
public:
    explicit unary_negate(const Pred& pr);
    bool operator()(const argument_type& x) const;
    };

The template class stores a copy of pr, which must be a unary function object. It defines its member function operator() as returning !pr(x).


 <iomanip>

<iomanip>

namespace std {
//      MANIPULATORS
T1 resetiosflags(ios_base::fmtflags mask);
T2 setiosflags(ios_base::fmtflags mask);
T3 setbase(int base);
template<class E>
    T4 setfill(E c);
T5 setprecision(int n);
T6 setw(int n);
    };

Include the iostreams standard header <iomanip> to define several manipulators that each take a single argument. Each of these manipulators returns an unspecified type, called T1 through T6 here, that overloads both basic_istream<E, T>:: operator>> and basic_ostream<E, T>:: operator<<. Thus, you can write extractors and inserters such as:

cin >> setbase(8);
cout << setbase(8);


resetiosflags

T1 resetiosflags(ios_base::fmtflags mask);

The manipulator returns an object that, when extracted from or inserted into the stream str, calls str. setf (ios_base:: fmtflags (), mask), then returns str.


setiosflags

T2 setiosflags(ios_base::fmtflags mask);

The manipulator returns an object that, when extracted from or inserted into the stream str, calls str. setf (mask), then returns str.


setbase

T3 setbase(int base);

The manipulator returns an object that, when extracted from or inserted into the stream str, calls str. setf (mask, ios_base:: basefield ), then returns str. Here, mask is determined as follows:

  • If base is 8, then mask is ios_base:: oct.
  • If base is 10, then mask is ios_base:: dec.
  • If base is 16, then mask is ios_base:: hex.
  • If base is any other value, then mask is ios_base:: fmtflags (0).


setfill

template<class E>
    T4 setfill(E fillch);

The template manipulator returns an object that, when extracted from or inserted into the stream str, calls str. fill (fillch), then returns str. The type E must be the same as the element type for the stream str.


setprecision

T5 setprecision(int prec);

The manipulator returns an object that, when extracted from or inserted into the stream str, calls str. precision (prec), then returns str.


setw

T6 setw(int wide);

The manipulator returns an object that, when extracted from or inserted into the stream str, calls str. width (wide), then returns str.


 <ios>

<ios>

basic_ios · fpos · ios · ios_base · streamoff · streampos · streamsize · wios · wstreampos

boolalpha · dec · fixed · hex · internal · left · noboolalpha · noshowbase · noshowpoint · noshowpos · noskipws · nounitbuf · nouppercase · oct · right · scientific · showbase · showpoint · showpos · skipws · unitbuf · uppercase

namespace std {
    typedef T1 streamoff;
    typedef T2 streamsize;
    class ios_base;
//      TEMPLATE CLASSES
    template <class E, class T = char_traits<E> >
        class basic_ios;
    typedef basic_ios<char, char_traits<char> > ios;
    typedef basic_ios<wchar_t, char_traits<wchar_t> > wios;
    template <class St>
        class fpos;
    typedef fpos<mbstate_t> streampos;
    typedef fpos<mbstate_t> wstreampos;
//      MANIPULATORS
    ios_base& boolalpha(ios_base& str);
    ios_base& noboolalpha(ios_base& str);
    ios_base& showbase(ios_base& str);
    ios_base& noshowbase(ios_base& str);
    ios_base& showpoint(ios_base& str);
    ios_base& noshowpoint(ios_base& str);
    ios_base& showpos(ios_base& str);
    ios_base& noshowpos(ios_base& str);
    ios_base& skipws(ios_base& str);
    ios_base& noskipws(ios_base& str);
    ios_base& unitbuf(ios_base& str);
    ios_base& nounitbuf(ios_base& str);
    ios_base& uppercase(ios_base& str);
    ios_base& nouppercase(ios_base& str);
    ios_base& internal(ios_base& str);
    ios_base& left(ios_base& str);
    ios_base& right(ios_base& str);
    ios_base& dec(ios_base& str);
    ios_base& hex(ios_base& str);
    ios_base& oct(ios_base& str);
    ios_base& fixed(ios_base& str);
    ios_base& scientific(ios_base& str);
    };

Include the iostreams standard header <ios> to define several types and functions basic to the operation of iostreams. (This header is typically included for you by another of the iostreams headers. You seldom have occasion to include it directly.)

A large group of functions are manipulators. The manipulators declared in <ios> alter the values stored in its argument object of class ios_base. Other manipulators perform actions on streams controlled by objects of a type derived from this class, such as a specialization of one of the template classes basic_istream or basic_ostream. For example, noskipws (istr) clears the format flag ios_base:: skipws in the object istr, which might be of type istream.

You can also call a manipulator by inserting it into an output stream or extracting it from an input stream, thanks to some special machinery supplied in the classes derived from ios_base. For example:

istr >> noskipws ;

calls noskipws(istr).


basic_ios

bad · basic_ios · char_type · clear · copyfmt · eof · exceptions · fail · good · imbue · init · int_type · narrow · off_type · operator! · operator void * · pos_type · rdbuf · rdstate · setstate · tie · widen

template <class E, class T = char_traits<E> >
    class basic_ios : public ios_base {
public:
    typedef E char_type;
    typedef T::int_type int_type;
    typedef T::pos_type pos_type;
    typedef T::off_type off_type;
    explicit basic_ios(basic_streambuf<E, T>* sb);
    virtual ~basic_ios();
    operator void *() const;
    bool operator!() const;
    iostate rdstate() const;
    void clear(iostate state = goodbit);
    void setstate(iostate state);
    bool good() const;
    bool eof() const;
    bool fail() const;
    bool bad() const;
    iostate exceptions() const;
    iostate exceptions(iostate except);
    basic_ios& copyfmt(const basic_ios& rhs);
    E fill() const;
    E fill(E ch);
    basic_ostream<E, T> *tie() const;
    basic_ostream<E, T> *tie(basic_ostream<E, T> *str);
    basic_streambuf<E, T> *rdbuf() const;
    basic_streambuf<E, T> *rdbuf(basic_streambuf<E, T> *sb);
    basic_ios& copyfmt(const basic_ios& rhs);
    locale imbue(const locale& loc);
    E widen(char ch);
    char narrow(E ch, char dflt);
protected:
    basic_ios();
    void init(basic_streambuf<E, T>* sb);
    };

The template class describes the storage and member functions common to both input streams (of template class basic_istream) and output streams (of template class basic_ostream) that depend on the template parameters. (The class ios_base describes what is common and not dependent on template parameters. An object of class basic_ios<E, T> helps control a stream with elements of type E, whose character traits are determined by the class T.

An object of class basic_ios<E, T> stores:

  • formatting information and stream state information in a base object of type ios_base
  • a fill character in an object of type E
  • a tie pointer to an object of type basic_ostream <E, T>
  • a stream buffer pointer to an object of type basic_streambuf <E, T>


basic_ios::bad

bool bad() const;

The member function returns true if rdstate () & badbit.


basic_ios::basic_ios

explicit basic_ios(basic_streambuf<E, T>* sb);
basic_ios();

The first constructor initializes its member objects by calling init (sb). The second (protected) constructor leaves its member objects uninitialized. A later call to init must initialize the object before it can be safely destroyed.


basic_ios::char_type

typedef E char_type;

The type is a synonym for the template parameter E.


basic_ios::clear

void clear(iostate state = goodbit);

The member function replaces the stored stream state information with state | ( rdbuf () != 0 ? goodbit : badbit). If state & exceptions () is nonzero, it then throws an object of class failure.


basic_ios::copyfmt

basic_ios& copyfmt(const basic_ios& rhs);

The member function reports the callback event erase_event. It then copies the fill character, the tie pointer, and the formatting information from rhs into *this. Before altering the exception mask, it reports the callback event copyfmt_event. If, after the copy is complete, state & exceptions () is nonzero, the function effectively calls clear with the argument rdstate (). It returns *this.


basic_ios::eof

bool eof() const;

The member function returns true if rdstate () & eofbit.


basic_ios::exceptions

iostate exceptions() const;
iostate exceptions(iostate except);

The first member function returns the stored exception mask. The second member function stores except in the exception mask and returns its previous stored value. Note that storing a new exception mask can throw an exception just like the call clear ( rdstate ()).


basic_ios::fail

bool fail() const;

The member function returns true if rdstate () & failbit.


basic_ios::fill

E fill() const;
E fill(E ch);

The first member function returns the stored fill character. The second member function stores ch in the fill character and returns its previous stored value.


basic_ios::good

bool good() const;

The member function returns true if rdstate () == goodbit (no state flags are set).


basic_ios::imbue

locale imbue(const locale& loc);

If rdbuf is not a null pointer, the member function calls rdbuf()-> pubimbue (loc). In any case, it returns ios_base::imbue (loc).


basic_ios::init

void init(basic_streambuf<E, T>* sb);

The member function stores values in all member objects, so that:

  • rdbuf () returns sb
  • tie () returns a null pointer
  • rdstate () returns goodbit if sb is nonzero; otherwise, it returns badbit
  • exceptions () returns goodbit
  • flags () returns skipws | dec
  • width () returns zero
  • precision () returns 6
  • fill () returns the space character
  • getloc () returns locale:: classic ()
  • iword returns zero and pword returns a null pointer for all argument values


basic_ios::int_type

typedef T::int_type int_type;

The type is a synonym for T:: int_type.


basic_ios::narrow

char narrow(E ch, char dflt);

The member function returns use_facet < ctype <E> >( getloc ()). narrow (ch, dflt).


basic_ios::off_type

typedef T::off_type off_type;

The type is a synonym for T:: off_type.


basic_ios::operator void *

operator void *() const;

The operator returns a null pointer only if fail ().


basic_ios::operator!

bool operator!() const;

The operator returns fail ().


basic_ios::pos_type

typedef T::pos_type pos_type;

The type is a synonym for T:: pos_type.


basic_ios::rdbuf

basic_streambuf<E, T> *rdbuf() const;
basic_streambuf<E, T> *rdbuf(basic_streambuf<E, T> *sb);

The member function returns the stored stream buffer pointer.


basic_ios::rdstate

iostate rdstate() const;

The member function returns the stored stream state information.


basic_ios::setstate

void setstate(iostate state);

The member function effectively calls clear (state | rdstate ()).


basic_ios::tie

basic_ostream<E, T> *tie() const;
basic_ostream<E, T> *tie(basic_ostream<E, T> *str);

The first member function returns the stored tie pointer. The second member function stores str in the tie pointer and returns its previous stored value.


basic_ios::widen

E narrow(char ch);

The member function returns use_facet < ctype <E> >( getloc ()). widen (ch).


boolalpha

ios_base& boolalpha(ios_base& str);

The manipulator effectively calls str. setf (ios_base:: boolalpha ), then returns str.


dec

ios_base& dec(ios_base& str);

The manipulator effectively calls str. setf (ios_base:: dec , ios_base:: basefield ), then returns str.


fixed

ios_base& fixed(ios_base& str);

The manipulator effectively calls str. setf (ios_base:: fixed , ios_base:: floatfield ), then returns str.


fpos

template <class St>
    class fpos {
public:
    fpos(St state, fpos_t fposn);
    fpos(streamoff off);
    fpos_t get_fpos_t() const;
    St state() const;
    void state(St state);
    operator streamoff() const;
    streamoff operator-(const fpos<St>& rhs) const;
    fpos<St>& operator+=(streamoff off);
    fpos<St>& operator-=(streamoff off);
    fpos<St> operator+(streamoff off) const;
    fpos<St> operator-(streamoff off) const;
    bool operator==(const fpos<St>& rhs) const;
    bool operator!=(const fpos<St>& rhs) const;
    };

The template class describes an object that can store all the information needed to restore an arbitrary file-position indicator within any stream. An object of class fpos<St> effectively stores three member objects:

  • A byte offset, of type streamoff
  • An arbitrary file position, for use by an object of class basic_filebuf, of type fpos_t
  • A conversion state, for use by an object of class basic_filebuf, of type St, typically mbstate_t

For an environment with limited file size, however, streamoff and fpos_t may sometimes be used interchangeably. And for an environment with no streams that have a state-dependent encoding, mbstate_t may actually be unused. So the number of member objects stored may well vary from one to three.


fpos::fpos

fpos(St state, fpos_t fposn);
fpos(streamoff off);

The first constructor stores a zero offset and the objects state and fposn. The second constructor stores the offset off, relative to the beginning of file and in the initial conversion state (if that matters). If off is -1, the resulting object represents an invalid stream position.


fpos::get_fpos_t

fpos_t get_fpos_t() const;

returns the value stored in the fpos_t member object.


fpos::operator!=

bool operator!=(const fpos<St>& rhs) const;

The member function returns !(*this == rhs).


fpos::operator+

fpos<St> operator+(streamoff off) const;

The member function returns fpos<St>(*this) += off.


fpos::operator+=

fpos<St>& operator+=(streamoff off);

The member function adds off to the stored offset member object, then returns *this. For positioning within a file, the result is generally valid only for binary streams that do not have a state-dependent encoding.


fpos::operator-

streamoff operator-(const fpos<St>& rhs) const;
fpos<St> operator-(streamoff off) const;

The first member function returns (streamoff)*this - (streamoff)rhs. The second member function returns fpos<St>(*this) -= off.


fpos::operator-=

fpos<St>& operator-=(streamoff off);

The member function returns fpos<St>(*this) -= off. For positioning within a file, the result is generally valid only for binary streams that do not have a state-dependent encoding.


fpos::operator==

bool operator==(const fpos<St>& rhs) const;

The member function returns (streamoff)*this == (streamoff)rhs.


fpos::operator streamoff

operator streamoff() const;

The member function returns the stored offset member object, plus any additional offset stored as part of the fpos_t member object.


fpos::state

St state() const;
void state(St state);

The first member function returns the value stored in the St member object. The second member function stores state in the St member object.


hex

ios_base& hex(ios_base& str);

The manipulator effectively calls str. setf (ios_base:: hex , ios_base:: basefield ), then returns str.


internal

ios_base& internal(ios_base& str);

The manipulator effectively calls str. setf (ios_base:: internal , ios_base:: adjustfield ), then returns str.


ios

typedef basic_ios<char, char_traits<char> > ios;

The type is a synonym for template class basic_ios, specialized for elements of type char with default character traits.


ios_base

event · event_callback · failure · flags · fmtflags · getloc · imbue · Init · ios_base · iostate · iword · openmode · operator= · precision · pword · register_callback · seekdir · setf · sync_with_stdio · unsetf · width · xalloc

class ios_base {
public:
    class failure;
    typedef T1 fmtflags;
    static const fmtflags boolalpha, dec, fixed, hex, internal,
        left, oct, right, scientific, showbase, showpoint,
        showpos, skipws, unitbuf, uppercase, adjustfield,
        basefield, floatfield;
    typedef T2 iostate;
    static const iostate badbit, eofbit, failbit, goodbit;
    typedef T3 openmode;
    static const openmode app, ate, binary, in, out, trunc;
    typedef T4 seekdir;
    static const seekdir beg, cur, end;
    typedef T5 event;
    static const event copyfmt_event, erase_event,
        copyfmt_event;
    class Init;
    ios_base& operator=(const ios_base& rhs);
    fmtflags flags() const;
    fmtflags flags(fmtflags fmtfl);
    fmtflags setf(fmtflags fmtfl);
    fmtflags setf(fmtflags fmtfl, fmtflags mask);
    void unsetf(fmtflags mask);
    streamsize precision() const;
    streamsize precision(streamsize prec);
    streamsize width() const;
    stramsize width(streamsize wide);
    locale imbue(const locale& loc);
    locale getloc() const;
    static int xalloc();
    long& iword(int idx);
    void *& pword(int idx);
    typedef void *(event_callback(event ev, ios_base& ios, int idx);
    void register_callback(event_callback pfn, int idx);
    static bool sync_with_stdio(bool sync = true);
protected:
    ios_base();
    };

The class describes the storage and member functions common to both input and output streams that do not depend on the template parameters. (The template class basic_ios describes what is common and is dependent on template parameters.)

An object of class ios_base stores formatting information, which consists of:

  • Format flags in an object of type fmtflags
  • An exception mask in an object of type iostate
  • A field width in an object of type int
  • A display precision in an object of type int
  • A locale object in an object of type locale
  • Two extensible arrays, with elements of type long and void pointer

An object of class ios_base also stores stream state information, in an object of type iostate, and a callback stack.


ios_base::event

typedef T5 event;
static const event copyfmt_event, erase_event,
    imbue_event;

The type is an enumerated type T5 that describes an object that can store the callback event used as an argument to a function registered with register_callback. The distinct event values are:

  • copyfmt_event, to identify a callback that occurs near the end of a call to copyfmt, just before the exception mask is copied.
  • erase_event, to identify a callback that occurs at the beginning of a call to copyfmt, or at the beginning of a call to the destructor for *this.
  • imbue_event, to identify a callback that occurs at the end of a call to imbue, just before the function returns.


ios_base::event_callback

typedef void *(event_callback(event ev, ios_base& ios, int idx);

The type describes a pointer to a function that can be registered with register_callback.


ios_base::failure

class failure : public exception {
public:
    explicit failure(const string& what_arg) {
    };

The member class serves as the base class for all exceptions thrown by the member function clear in template class basic_ios. The value returned by what () is what_arg. data ().


ios_base::flags

fmtflags flags() const;
fmtflags flags(fmtflags fmtfl);

The first member function returns the stored format flags. The second member function stores fmtfl in the format flags and returns its previous stored value.


ios_base::fmtflags

typedef T1 fmtflags;
static const fmtflags boolalpha, dec, fixed, hex, internal,
    left, oct, right, scientific, showbase, showpoint,
    showpos, skipws, unitbuf, uppercase, adjustfield,
    basefield, floatfield;

The type is an enumerated type T1 that describes an object that can store format flags. The distinct flag values are:

  • boolalpha, to insert or extract objects of type bool as names (such as true and false) rather than as numeric values.
  • dec, to insert or extract integer values in decimal format.
  • fixed, to insert floating-point values in fixed-point format (with no exponent field).
  • hex, to insert or extract integer values in hexadecimal format.
  • internal, to pad to a field width as needed by inserting fill characters at a point internal to a generated numeric field.
  • left, to pad to a field width as needed by inserting fill characters at the end of a generated field (left justification).
  • oct, to insert or extract integer values in octal format.
  • right, to pad to a field width as needed by inserting fill characters at the beginning of a generated field (right justification).
  • scientific, to insert floating-point values in scientific format (with an exponent field).
  • showbase, to insert a prefix that reveals the base of a generated integer field.
  • showpoint, to insert a decimal point unconditionally in a generated floating-point field.
  • showpos, to insert a plus sign in a non-negative generated numeric field.
  • skipws, to skip leading white space before certain extractions.
  • unitbuf, to flush output after each insertion.
  • uppercase, to insert uppercase equivalents of lowercase letters in certain insertions.

In addition, several useful values are:

  • adjustfield, internal | left | right
  • basefield, dec | hex | oct
  • floatfield, fixed | scientific


ios_base::getloc

locale getloc() const;

The member function returns the stored locale object.


ios_base::imbue

locale imbue(const locale& loc);

The member function stores loc in the locale object, then reports the callback event imbue_event. It returns the previous stored value.


ios_base::Init

class Init {
    };

The nested class describes an object whose construction ensures that the standard iostreams objects are properly constructed, even during the execution of a constructor for an arbitrary static object.


ios_base::ios_base

ios_base();

The (protected) constructor does nothing. A later call to basic_ios:: init must initialize the object before it can be safely destroyed. Thus, the only safe use for class ios_base is as a base class for template class basic_ios.


ios_base::iostate

typedef T2 iostate;
static const iostate badbit, eofbit, failbit, goodbit;

The type is an enumerated type T2 that describes an object that can store stream state information. The distinct flag values are:

  • badbit, to record a loss of integrity of the stream buffer
  • eofbit, to record end-of-file while extracting from a stream
  • failbit, to record a failure to extract a valid field from a stream

In addition, a useful value is:

  • goodbit, no bits set


ios_base::iword

long& iword(int idx);

The member function returns a reference to element idx of the extensible array with elements of type long. All elements are effectively present and initially store the value zero. The returned reference is invalid after the next call to iword for the object, after the object is altered by a call to basic_ios:: copyfmt, or after the object is destroyed.

To obtain a unique index for use across all objects of type ios_base, call xalloc.


ios_base::openmode

typedef T3 openmode;
static const openmode app, ate, binary, in, out, trunc;

The type is an enumerated type T3 that describes an object that can store the opening mode for several iostreams objects. The distinct flag values are:

  • app, to seek to the end of a stream before each insertion
  • ate, to seek to the end of a stream when its controlling object is first created
  • binary, to read a file as a binary stream, rather than as a text stream
  • in, to permit extraction from a stream
  • out, to permit insertion to a stream
  • trunc, to truncate an existing file when its controlling object is first created


ios_base::operator=

ios_base& operator=(const ios_base& rhs) const;

The operator copies the stored formatting information, making a new copy of any extensible arrays. It then returns *this. Note that the callback stack is not copied.


ios_base::precision

streamsize precision() const;
streamsize precision(streamsize prec);

The first member function returns the stored display precision. The second member function stores prec in the display precision and returns its previous stored value.


ios_base::pword

void *& pword(int idx);

The member function returns a reference to element idx of the extensible array with elements of type void pointer. All elements are effectively present and initially store the null pointer. The returned reference is invalid after the next call to pword for the object, after the object is altered by a call to basic_ios:: copyfmt, or after the object is destroyed.

To obtain a unique index for use across all objects of type ios_base, call xalloc.


ios_base::register_callback

void register_callback(event_callback pfn, int idx);

The member function pushes the pair {pfn, idx} onto the stored callback stack. When a callback event ev is reported, the functions are called, in reverse order of registry, by the expression (*pfn)(ev, *this, idx).


ios_base::seekdir

typedef T4 seekdir;
static const seekdir beg, cur, end;

The type is an enumerated type T4 that describes an object that can store the seek mode used as an argument to the member functions of several iostreams classes. The distinct flag values are:

  • beg, to seek (alter the current read or write position) relative to the beginning of a sequence (array, stream, or file)
  • cur, to seek relative to the current position within a sequence
  • end, to seek relative to the end of a sequence


ios_base::setf

void setf(fmtflags mask);
fmtflags setf(fmtflags fmtfl, fmtflags mask);

The first member function effectively calls flags (mask | flags()) (set selected bits), then returns the previous format flags. The second member function effectively calls flags(mask & fmtfl, flags() & ~mask) (replace selected bits under a mask), then returns the previous format flags.


ios_base::sync_with_stdio

static bool sync_with_stdio(bool sync = true);

The static member function stores a stdio sync flag, which is initially true. When true, this flag ensures that operations on the same file are properly synchronized between the iostreams functions and those defined in the Standard C library. Otherwise, synchronization may or may not be guaranteed, but performance may be improved. The function stores sync in the stdio sync flag and returns its previous stored value. You can call it reliably only before performing any operations on the standard streams.


ios_base::unsetf

void unsetf(fmtflags mask);

The member function effectively calls flags (~mask & flags()) (clear selected bits).


ios_base::width

streamsize width() const;
streamsize width(streamsize wide);

The first member function returns the stored field width. The second member function stores wide in the field width and returns its previous stored value.


ios_base::xalloc

static int xalloc();

The static member function returns a stored static value, which it increments on each call. You can use the return value as a unique index argument when calling the member functions iword or pword.


left

ios_base& left(ios_base& str);

The manipulator effectively calls str. setf (ios_base:: left , ios_base:: adjustfield ), then returns str.


noboolalpha

ios_base& noboolalpha(ios_base& str);

The manipulator effectively calls str. unsetf (ios_base:: boolalpha ), then returns str.


noshowbase

ios_base& noshowbase(ios_base& str);

The manipulator effectively calls str. unsetf (ios_base:: showbase ), then returns str.


noshowpoint

ios_base& noshowpoint(ios_base& str);

The manipulator effectively calls str. unsetf (ios_base:: showpoint ), then returns str.


noshowpos

ios_base& noshowpos(ios_base& str);

The manipulator effectively calls str. unsetf (ios_base:: showpos ), then returns str.


noskipws

ios_base& noskipws(ios_base& str);

The manipulator effectively calls str. unsetf (ios_base:: skipws ), then returns str.


nounitbuf

ios_base& nounitbuf(ios_base& str);

The manipulator effectively calls str. unsetf (ios_base:: unitbuf ), then returns str.


nouppercase

ios_base& nouppercase(ios_base& str);

The manipulator effectively calls str. unsetf (ios_base:: uppercase ), then returns str.


oct

ios_base& oct(ios_base& str);

The manipulator effectively calls str. setf (ios_base:: oct , ios_base:: basefield ), then returns str.


right

ios_base& right(ios_base& str);

The manipulator effectively calls str. setf (ios_base:: right , ios_base:: adjustfield ), then returns str.


scientific

ios_base& scientific(ios_base& str);

The manipulator effectively calls str. setf (ios_base:: scientific , ios_base:: floatfield ), then returns str.


showbase

ios_base& showbase(ios_base& str);

The manipulator effectively calls str. setf (ios_base:: showbase ), then returns str.


showpoint

ios_base& showpoint(ios_base& str);

The manipulator effectively calls str. setf (ios_base:: showpoint ), then returns str.


showpos

ios_base& showpos(ios_base& str);

The manipulator effectively calls str. setf (ios_base:: showpos ), then returns str.


skipws

ios_base& skipws(ios_base& str);

The manipulator effectively calls str. setf (ios_base:: skipws ), then returns str.


streamoff

typedef T1 streamoff;

The type is a signed integer type T1 that describes an object that can store a byte offset involved in various stream positioning operations. Its representation has at least 32 value bits. It is not necessarily large enough to represent an arbitrary byte position within a stream. The value streamoff(-1) generally indicates an erroneous offset.


streampos

typedef fpos<mbstate_t> streampos;

The type is a synonym for fpos < mbstate_t >.


streamsize

typedef T2 streamsize;

The type is a signed integer type T3 that describes an object that can store a count of the number of elements involved in various stream operations. Its representation has at least 16 bits. It is not necessarily large enough to represent an arbitrary byte position within a stream.


unitbuf

ios_base& unitbuf(ios_base& str);

The manipulator effectively calls str. setf (ios_base:: unitbuf ), then returns str.


uppercase

ios_base& uppercase(ios_base& str);

The manipulator effectively calls str. setf (ios_base:: uppercase ), then returns str.


wios

typedef basic_ios<wchar_t, char_traits<wchar_t> > wios;

The type is a synonym for template class basic_ios, specialized for elements of type wchar_t with default character traits.


wstreampos

typedef fpos<mbstate_t> wstreampos;

The type is a synonym for fpos < mbstate_t >.


 <iosfwd>

<iosfwd>

namespace std {
        // TYPE DEFINITIONS
typedef T1 streamoff;
typedef T2 streampos;
        // TEMPLATES
template<class E>
    class char_traits;
class char_traits<char>;
class char_traits<wchar_t>;
template<class E, class T = char_traits<E> >
    class basic_ios;
template<class E, class T = char_traits<E> >
    class istreambuf_iterator;
template<class E, class T = char_traits<E> >
    class ostreambuf_iterator;
template<class E, class T = char_traits<E> >
    class basic_streambuf;
template<class E, class T = char_traits<E> >
    class basic_istream;
template<class E, class T = char_traits<E> >
    class basic_ostream;
template<class E, class T = char_traits<E> >
    class basic_iostream;
template<class E, class T = char_traits<E> >
    class basic_stringbuf;
template<class E, class T = char_traits<E> >
    class basic_istringstream;
template<class E, class T = char_traits<E> >
    class basic_ostringstream;
template<class E, class T = char_traits<E> >
    class basic_stringstream;
template<class E, class T = char_traits<E> >
    class basic_filebuf;
template<class E, class T = char_traits<E> >
    class basic_ifstream;
template<class E, class T = char_traits<E> >
    class basic_ofstream;
template<class E, class T = char_traits<E> >
    class basic_fstream;
        // char TYPE DEFINITIONS
typedef basic_ios<char, char_traits<char> > ios;
typedef basic_streambuf<char, char_traits<char> > streambuf;
typedef basic_istream<char, char_traits<char> > istream;
typedef basic_ostream<char, char_traits<char> > ostream;
typedef basic_iostream<char, char_traits<char> > iostream;
typedef basic_stringbuf<char, char_traits<char> > stringbuf;
typedef basic_istringstream<char, char_traits<char> > istringstream;
typedef basic_ostringstream<char, char_traits<char> > ostringstream;
typedef basic_stringstream<char, char_traits<char> > stringstream;
typedef basic_filebuf<char, char_traits<char> > filebuf;
typedef basic_ifstream<char, char_traits<char> > ifstream;
typedef basic_ofstream<char, char_traits<char> > ofstream;
typedef basic_fstream<char, char_traits<char> > fstream;
        // wchar_t TYPE DEFINITIONS
typedef basic_ios<wchar_t, char_traits<wchar_t> > wios;
typedef basic_streambuf<wchar_t, char_traits<wchar_t> > wstreambuf;
typedef basic_istream<wchar_t, char_traits<wchar_t> > wistream;
typedef basic_ostream<wchar_t, char_traits<wchar_t> > wostream;
typedef basic_iostream<wchar_t, char_traits<wchar_t> > wiostream;
typedef basic_stringbuf<wchar_t, char_traits<wchar_t> > wstringbuf;
typedef basic_istringstream<wchar_t, char_traits<wchar_t> > wistringstream;
typedef basic_ostringstream<wchar_t, char_traits<wchar_t> > wostringstream;
typedef basic_stringstream<wchar_t, char_traits<wchar_t> > wstringstream;
typedef basic_filebuf<wchar_t, char_traits<wchar_t> > wfilebuf;
typedef basic_ifstream<wchar_t, char_traits<wchar_t> > wifstream;
typedef basic_ofstream<wchar_t, char_traits<wchar_t> > wofstream;
typedef basic_fstream<wchar_t, char_traits<wchar_t> > wfstream;
    };

Include the iostreams standard header <iosfwd> to declare forward references to several template classes used throughout iostreams. All such template classes are defined in other standard headers. You include this header explicitly only when you need one of the above declarations, but not its definition.


 <iostream>

<iostream>

namespace std {
    extern istream cin;
    extern ostream cout;
    extern ostream cerr;
    extern ostream clog;
    extern wistream wcin;
    extern wostream wcout;
    extern wostream wcerr;
    extern wostream wclog;
    };

Include the iostreams standard header <iostream> to declare objects that control reading from and writing to the standard streams. This is often the only header you need include to perform input and output from a C++ program.

The objects fall into two groups:

  • cin, cout, cerr, and clog are byte oriented, performing conventional byte-at-a-time transfers.
  • wcin, wcout, wcerr, and wclog are wide oriented, translating to and from the wide characters that the program manipulates internally.

Once you perform certain operations on a stream, such as the standard input, you cannot perform operations of a different orientation on the same stream. A program cannot operate interchangeably on both cin and wcin, for example.

All the objects declared in this header share a peculiar property: You can assume they are constructed before any static objects you define, in a translation unit that includes <iostreams>. Equally, you can assume that these objects are not destroyed before the destructors for any such static objects you define. (The output streams are, however, flushed during program termination.) You can safely read from or write to the standard streams prior to program startup and after program termination.

This guarantee is not universal, however. A static constructor may call a function in another translation unit. The called function cannot assume that the objects declared in this header have been constructed, given the uncertain order in which translation units participate in static construction. To use these objects in such a context, you must first construct an object of class ios_base::Init, as in:

#include <iostream>

using namespace std;

void marker()
    {    // called by some constructor
    ios_base::Init unused_name;
    cout << "called fun" << endl;
    }


cerr

extern ostream cerr;

The object controls unbuffered insertions to the standard error output as a byte stream. Once the object is constructed, the expression cerr. flags () & unitbuf is nonzero.


cin

extern istream cin;

The object controls extractions from the standard input as a byte stream. Once the object is constructed, the call cin. tie () returns & cout.


clog

extern ostream clog;

The object controls buffered insertions to the standard error output as a byte stream.


cout

extern ostream cout;

The object controls insertions to the standard output as a byte stream.


wcerr

extern wostream wcerr;

The object controls unbuffered insertions to the standard error output as a wide stream. Once the object is constructed, the expression wcerr. flags () & unitbuf is nonzero.


wcin

extern wistream wcin;

The object controls extractions from the standard input as a wide stream. Once the object is constructed, the call wcin. tie () returns & wcout.


wclog

extern wostream wclog;

The object controls buffered insertions to the standard error output as a wide stream.


wcout

extern wostream wcout;

The object controls insertions to the standard output as a wide stream.


 <istream>

<istream>

namespace std {

        // DECLARATIONS
    template<class E, class T = char_traits<E> >
        class basic_istream;
    typedef basic_istream<char, char_traits<char> > istream;
    typedef basic_istream<wchar_t, char_traits<wchar_t> > wistream;
    template<class E, class T = char_traits<E> >
        class basic_iostream;
    typedef basic_iostream<char, char_traits<char> > iostream;
    typedef basic_iostream<wchar_t, char_traits<wchar_t> > wiostream;
//      EXTRACTORS
    template<class E, class T>
        basic_istream<E, T>& operator>>(basic_istream<E, T> is, E *s);
    template<class E, class T>
        basic_istream<E, T>& operator>>(basic_istream<E, T> is, E& c);
    template<class T>
        basic_istream<char, T>& operator>>(basic_istream<char, T> is, signed char *s);
    template<class T>
        basic_istream<char, T>& operator>>(basic_istream<char, T> is, signed char& c);
    template<class T>
        basic_istream<char, T>& operator>>(basic_istream<char, T> is, unsigned char *s);
    template<class T>
        basic_istream<char, T>& operator>>(basic_istream<char, T> is, unsigned char& c);
//      MANIPULATOR
    template class<E, T>
        basic_istream<E, T>& ws(basic_istream<E, T> is);
    };

Include the iostreams standard header <istream> to define template class basic_istream, which mediates extractions for the iostreams, and the template class basic_iostream, which mediates both insertions and extractions. The header also defines a related manipulator. (This header is typically included for you by another of the iostreams headers. You seldom have occasion to include it directly.)


basic_iostream

template <class E, class T = char_traits<E> >
    class basic_iostream : public basic_istream<E, T>,
        public  basic_ostream<E, T> {
public:
    explicit basic_iostream(basic_streambuf<E, T> *sb);
    virtual ~basic_iostream();
    };

The template class describes an object that controls insertions, through its base object basic_ostream <E, T>, and extractions, through its base object basic_istream <E, T>. The two objects share a common virtual base object basic_ios <E, T>. They also manage a common stream buffer, with elements of type E, whose character traits are determined by the class T. The constructor initializes its base objects via basic_istream(sb) and basic_ostream(sb).


basic_istream

basic_istream · gcount · get · getline · ignore · ipfx · isfx · operator>> · peek · putback · read · readsome · seekg · sentry · sync · tellg · unget

template <class E, class T = char_traits<E> >
    class basic_istream : virtual public basic_ios<E, T> {
public:
    class sentry;
    explicit basic_istream(basic_streambuf<E, T> *sb);
    virtual ~istream();
    bool ipfx(bool noskip = false);
    void isfx();
    basic_istream& operator>>(basic_istream& (*pf)(basic_istream&));
    basic_istream& operator>>(basic_ios<E, T>& (*pf)(basic_ios<E, T>&));
    basic_istream& operator>>(ios_base<E, T>& (*pf)(ios_base<E, T>&));
    basic_istream& operator>>(basic_streambuf<E, T> *sb);
    basic_istream& operator>>(bool& n);
    basic_istream& operator>>(short& n);
    basic_istream& operator>>(unsigned short& n);
    basic_istream& operator>>(int& n);
    basic_istream& operator>>(unsigned int& n);
    basic_istream& operator>>(long& n);
    basic_istream& operator>>(unsigned long& n);
    basic_istream& operator>>(void *& n);
    basic_istream& operator>>(float& n);
    basic_istream& operator>>(double& n);
    basic_istream& operator>>(long double& n);
    streamsize gcount() const;
    int_type get();
    basic_istream& get(E& c);
    basic_istream& get(E *s, streamsize n);
    basic_istream& get(E *s, streamsize n, E delim);
    basic_istream& get(basic_streambuf<E, T> *sb);
    basic_istream& get(baiic_streambuf<E, T> *sb, E delim);
    basic_istream& getline(E *s, streamsize n)E
    basic_istream& getline(E *s, streamsize n, E delim);
    basic_istream& ignore(streamsize n = 1,
        int_type delim = T::eof());
    int_type peek();
    basic_istream& read(E *s, streamsize n);
    streamsize readsome(E *s, streamsize n);
    basic_istream& putback(E c);
    basic_istream& unget();
    pos_type tellg();
    basic_istream& seekg(pos_type pos);
    basic_istream& seekg(off_type off, ios_base::seek_dir way);
    int sync();
    };

The template class describes an object that controls extraction of elements and encoded objects from a stream buffer with elements of type E, whose character traits are determined by the class T.

Most of the member functions that overload operator>> are formatted input functions. They follow the pattern:

    iostate state = goodbit;
    const sentry ok(*this);
    if (ok)
        {try
            {extract elements and convert
            accumulate flags in state
            store a successful conversion}
        catch (...)
            {if (exceptions() & badbit)
                throw;
            setstate(badbit); }}
    setstate(state);
    return (*this);

Many other member functions are unformatted input functions. They follow the pattern:

    iostate state = goodbit;
    count = 0;    // the value returned by gcount
    const sentry ok(*this, true);
    if (ok)
        {try
            {extract elements and deliver
            count extracted elements in count
            accumulate flags in state}
        catch (...)
            {if (rdstate() & badbit)
                throw;
            setstate(badbit); }}
    setstate(state);

Both groups of functions call setstate(eofbit) if they encounter end-of-file while extracting elements.

An object of class basic_istream<E, T> stores:

  • A virtual public base object of class basic_ios<E, T>.
  • An extraction count for the last unformatted input operation (called count in the code above).


basic_istream::basic_istream

explicit basic_istream(basic_streambuf<E, T> *sb);

The constructor initializes the base class by calling init (sb). It also stores zero in the extraction count.


basic_istream::gcount

streamsize gcount() const;

The member function returns the extraction count.


basic_istream::get

int_type get();
basic_istream& get(E& c);
basic_istream& get(E *s, streamsize n);
basic_istream& get(E *s, streamsize n, E delim);
basic_istream& get(basic_streambuf<E, T> *sb);
basic_istream& get(basic_streambuf<E, T> *sb, E delim);

The first of these unformatted input functions extracts an element, if possible, as if by returning rdbuf()-> sbumpc (). Otherwise, it returns T:: eof (). If the function extracts no element, it calls setstate (failbit).

The second function extracts the int_type element x the same way. If x compares equal to T:: eof (x), the function calls setstate (failbit). Otherwise, it stores T:: to_char_type (x) in c. The function returns *this.

The third function returns get(s, n, widen('\n')).

The fourth function extracts up to n - 1 elements and stores them in the array beginning at s. It always stores E(0) after any extracted elements it stores. Extraction stops early on end-of-file or on an element that compares equal to delim (which is not extracted). If the function extracts no elements, it calls setstate (failbit). In any case, it returns *this.

The fifth function returns get(sb, widen('\n')).

The sixth function extracts elements and inserts them into sb. Extraction stops on end-of-file or on an element that compares equal to delim (which is not extracted). It also stops, without extracting the element in question, if an insertion fails or throws an exception (which is caught but not rethrown). If the function extracts no elements, it calls setstate (failbit). In any case, the function returns *this.


basic_istream::getline

basic_istream& getline(E *s, streamsize n);
basic_istream& getline(E *s, streamsize n, E delim);

The first of these unformatted input functions returns getline(s, n, widen('\n')).

The second function extracts up to n - 1 elements and stores them in the array beginning at s. It always stores E(0) after any extracted elements it stores. In order of testing, extraction stops:

  1. At end of file.
  2. After the function extracts an element that compares equal to delim, in which case the element is neither put back nor appended to the controlled sequence.
  3. After the function extracts is. max_size () elements.

If the function extracts no elements, it calls setstate (failbit). In any case, it returns *this.


basic_istream::ignore

basic_istream& ignore(streamsize n = 1,
    int_type delim = T::eof());

The unformatted input function extracts up to n elements and discards them. If n equals numeric_limits<int>:: max (), however, it is taken as arbitrarily large. Extraction stops early on end-of-file or on an element x such that T:: to_int_type (x) compares equal to delim (which is also extracted). The function returns *this.


basic_istream::ipfx

bool ipfx(bool noskip = false);

The member function prepares for formatted or unformatted input. If good () is true, the function:

  • Calls tie -> flush () if tie() is not a null pointer.
  • Effectively calls ws (*this) if flags () & skipws is nonzero.

If, after any such preparation, good() is false, the function calls setstate (failbit). In any case, the function returns good().

You should not call ipfx directly. It is called as needed by an object of class sentry.


basic_istream::isfx

void isfx();

The member function has no official duties, but an implementation may depend on a call to isfx by a formatted or unformatted input function to tidy up after an extraction. You should not call isfx directly. It is called as needed by an object of class sentry.


basic_istream::operator>>

basic_istream& operator>>(
    basic_istream& (*pf)(basic_istream&));
basic_istream& operator>>(
    basic_ios<E, T>& (*pf)(basic_ios<E, T>&));
basic_istream& operator>>(
    ios_base<E, T>& (*pf)(ios_base<E, T>&));
basic_istream& operator>>(
    basic_streambuf<E, T> *sb);
basic_istream& operator>>(bool& n);
basic_istream& operator>>(short& n);
basic_istream& operator>>(unsigned short& n);
basic_istream& operator>>(int& n);
basic_istream& operator>>(unsigned int& n);
basic_istream& operator>>(long& n);
basic_istream& operator>>(unsigned long& n);
basic_istream& operator>>(void *& n);
basic_istream& operator>>(float& n);
basic_istream& operator>>(double& n);
basic_istream& operator>>(long double& n);

The first member function ensures that an expression of the form istr >>: ws calls ws (istr), then returns *this. The second and third functions ensure that other manipulators, such as hex, behave similarly. The remaining functions constitute the formatted input functions.

The function:

basic_istream& operator>>(
    basic_streambuf<E, T> *sb);

extracts elements, if sb is not a null pointer, and inserts them into sb. Extraction stops on end-of-file. It also stops, without extracting the element in question, if an insertion fails or throws an exception (which is caught but not rethrown). If the function extracts no elements, it calls setstate (failbit). In any case, the function returns *this.

The function:

basic_istream& operator>>(bool& n);

extracts a field and converts it to a Boolean value by calling use_facet <num_get<E, InIt>( getloc ()). get (InIt( rdbuf ()), Init(0), *this, getloc(), n). Here, InIt is defined as istreambuf_iterator <E, T>. The function returns *this.

The functions:

basic_istream& operator>>(short& n);
basic_istream& operator>>(unsigned short& n);
basic_istream& operator>>(int& n);
basic_istream& operator>>(unsigned int& n);
basic_istream& operator>>(long& n);
basic_istream& operator>>(unsigned long& n);
basic_istream& operator>>(void *& n);

each extract a field and convert it to a numeric value by calling use_facet <num_get<E, InIt>( getloc ()). get (InIt( rdbuf ()), Init(0), *this, getloc(), x). Here, InIt is defined as istreambuf_iterator <E, T>, and x has type long, unsigned long, or void * as needed. If the converted value cannot be represented as the type of n, the function calls setstate (failbit). In any case, it returns *this.

The functions:

basic_istream& operator>>(float& n);
basic_istream& operator>>(double& n);
basic_istream& operator>>(long double& n);

each extract a field and convert it to a numeric value by calling use_facet <num_get<E, InIt>( getloc ()). get (InIt( rdbuf ()), Init(0), *this, getloc(), x). Here, InIt is defined as istreambuf_iterator <E, T>, and x has type double or long double as needed. If the converted value cannot be represented as the type of n, the function calls setstate (failbit). In any case, it returns *this.


basic_istream::peek

int_type peek();

The unformatted input function extracts an element, if possible, as if by returning rdbuf()-> sgetc (). Otherwise, it returns T:: eof ().


basic_istream::putback

basic_istream& putback(E c);

The unformatted input function puts back c, if possible, as if by calling rdbuf()-> sputbackc (). If rdbuf () is a null pointer, or if the call to sputbackc returns T:: eof (), the function calls setstate (badbit). In any case, it returns *this.


basic_istream::read

basic_istremm& read(E *s, streamsize n);

The unformatted input function extracts up to n elements and stores them in the array beginning at s. Extraction stops early on end-of-file, in which case the function calls setstate (failbit). In any case, it returns *this.


basic_istream::readsome

readsome readsome(E *s, streamsize n);

The member function extracts up to n elements and stores them in the array beginning at s. If rdbuf () is a null pointer, the function calls setstate (failbit). Otherwise, it assigns the value of rdbuf()-< in_avail () to N. if N < 0, the function calls setstate (eofbit). Otherwise, it replaces the value stored in N with the smaller of n and N, then calls read (s, N). In any case, the function returns gcount ().


basic_istream::seekg

basic_istream& seekg(pos_type pos);
basic_istream& seekg(off_type off, ios_base::seek_dir way);

If fail () is false, the first member function calls rdbuf ()-> pubseekpos (pos). If fail() is false, the second function calls rdbuf()-> pubseekoff (off, way). Both functions return *this.


basic_istream::sentry

class sentry {
public:
    explicit sentry(basic_istream<E, T>& is, bool noskip = false);
    operator bool() const;
    };

The nested class describes an object whose declaration structures the formatted input functions and the unformatted input functions. The constructor effectively calls is. ipfx (noskip) and stores the return value. operator bool() delivers this return value. The destructor effectively calls is. isfx ().


basic_istream::sync

int sync();

If rdbuf () is a null pointer, the function returns -1. Otherwise, it calls rdbuf()-> pubsync (). If that returns -1, the function calls setstate (badbit) and returns -1. Otherwise, the function returns zero.


basic_istream::tellg

pos_type tellg();

If fail () is false, the member function returns rdbuf ()-> pubseekoff (0, cur , in ). Otherwise, it returns streampos(-1).


basic_istream::unget

basic_istream& unget();

The unformatted input function puts back the previous element in the stream, if possible, as if by calling rdbuf()-> sungetc (). If rdbuf () is a null pointer, or if the call to sungetc returns T:: eof (), the function calls setstate (badbit). In any case, it returns *this.


iostream

typedef basic_iostream<char, char_traits<char> > iostream;

The type is a synonym for template class basic_iostream, specialized for elements of type char with default character traits.


istream

typedef basic_istream<char, char_traits<char> > istream;

The type is a synonym for template class basic_istream, specialized for elements of type char with default character traits.


operator>>

template<class E, class T>
    basic_istream<E, T>& operator>>(basic_istream<E, T> is, E *s);
template<class E, class T>
    basic_istream<E, T>& operator>>(basic_istream<E, T> is, E& c);
template<class T>
    basic_istream<char, T>& operator>>(basic_istream<char, T> is, signed char *s);
template<class T>
    basic_istream<char, T>& operator>>(basic_istream<char, T> is, signed char& c);
template<class T>
    basic_istream<char, T>& operator>>(basic_istream<char, T> is, unsigned char *s);
template<class T>
    basic_istream<char, T>& operator>>(basic_istream<char, T> is, unsigned char& c);

The template function:

template<class E, class T>
    basic_istream<E, T>& operator>>(basic_istream<E, T>& is, E *s);

extracts up to n - 1 elements and stores them in the array beginning at s. If is. width () is greater than zero, n is is.width(); otherwise it is the largest array of E that can be declared. The function always stores E(0) after any extracted elements it stores. Extraction stops early on end-of-file or on any element (which is not extracted) that would be discarded by ws. If the function extracts no elements, it calls is. setstate (failbit). In any case, it calls is.width(0) and returns is.

The template function:

template<class E, class T>
    basic_istream<E, T>& operator>>(basic_istream<E, T>& is, char& c);

extracts an element, if possible, and stores it in c. Otherwise, it calls is. setstate (failbit). In any case, it returns is.

The template function:

template<class T>
    basic_istream<char, T>& operator>>(basic_istream<char, T> is, signed char *s);

returns is >> (char *)s.

The template function:

template<class T>
    basic_istream<char, T>& operator>>(basic_istream<char, T> is, signed char& c);

returns is >> (char&)c.

The template function:

template<class T>
    basic_istream<char, T>& operator>>(basic_istream<char, T> is, unsigned char *s);

returns is >> (char *)s.

The template function:

template<class T>
    basic_istream<char, T>& operator>>(basic_istream<char, T> is, unsigned char& c);

returns is >> (char&)c.


wiostream

typedef basic_iostream<wchar_t, char_traits<wchar_t> > wiostream;

The type is a synonym for template class basic_iostream, specialized for elements of type wchar_t with default character traits.


wistream

typedef basic_istream<wchar_t, char_traits<wchar_t> > wistream;

The type is a synonym for template class basic_istream, specialized for elements of type wchar_t with default character traits.


ws

template class<E, T>
    basic_istream<E, T>& ws(basic_istream<E, T> is);

The manipulator extracts and discards any elements x for which use_facet < ctype <E> >( getloc ()). is ( ctype<E>:: space , x) is true. It calls setstate (eofbit) if it encounters end-of-file while extracting elements. The function returns is.


 <iterator>

<iterator>

advance · back_insert_iterator · back_inserter · bidirectional_iterator_tag · distance · forward_iterator_tag · front_insert_iterator · front_inserter · input_iterator_tag · insert_iterator · inserter · istream_iterator · istreambuf_iterator · iterator · iterator_traits · operator!= · operator== · operator< · operator<= · operator> · operator>= · operator+ · operator- · ostream_iterator · ostreambuf_iterator · output_iterator_tag · random_access_iterator_tag · reverse_bidirectional_iterator · reverse_iterator

namespace std {
struct input_iterator_tag;
struct output_iterator_tag;
struct forward_iterator_tag;
struct bidirectional_iterator_tag;
struct random_access_iterator_tag;
//    TEMPLATE CLASSES
template<class C, class T, class Dist>
    struct iterator;
template<class It>
    struct iterator_traits;
template<class T>
    struct iterator_traits<T *>
template<class BidIt, class T, class Ref,
    class Ptr, class Dist>
    class reverse_bidirectional_iterator;
template<class RanIt, class T, class Ref,
    class Ptr, class Dist>
    class reverse_iterator;
template<class Cont>
    class back_insert_iterator;
template<class Cont>
    class front_insert_iterator;
template<class Cont>
    class insert_iterator;
template<class T, class Dist>
    class istream_iterator;
template<class T>
    class ostream_iterator;
template<class E, class T>
    class istreambuf_iterator;
template<class E, class T>
    class ostreambuf_iterator;
//    TEMPLATE FUNCTIONS
template<class BidIt, class T, class Ref, class Ptr, class Dist>
    bool operator==(
        const reverse_bidirectional_iterator<BidIt, T, Ref,
            Ptr, Dist>& lhs,
        const reverse_bidirectional_iterator<BidIt, T, Ref,
            Ptr, Dist>& rhs);
template<class RanIt, class T, class Ref, class Ptr, class Dist>
    bool operator==(
        const reverse_iterator<RanIt, T, Ref, Ptr, Dist>& lhs,
        const reverse_iterator<RanIt, T, Ref, Ptr, Dist>& rhs);
template<class T, class Dist>
    bool operator==(
        const istream_iterator<T, Dist>& lhs,
        const istream_iterator<T, Dist>& rhs);
template<class E, class T>
    bool operator==(
        const istreambuf_iterator<E, T>& lhs,
        const istreambuf_iterator<E, T>& rhs);
template<class BidIt, class T, class Ref, class Ptr, class Dist>
    bool operator!=(
        const reverse_bidirectional_iterator<BidIt, T, Ref,
            Ptr, Dist>& lhs,
        const reverse_bidirectional_iterator<BidIt, T, Ref,
            Ptr, Dist>& rhs);
template<class RanIt, class T, class Ref, class Ptr, class Dist>
    bool operator!=(
        const reverse_iterator<RanIt, T, Ref, Ptr, Dist>& lhs,
        const reverse_iterator<RanIt, T, Ref, Ptr, Dist>& rhs);
template<class T, class Dist>
    bool operator!=(
        const istream_iterator<T, Dist>& lhs,
        const istream_iterator<T, Dist>& rhs);
template<class E, class T>
    bool operator!=(
        const istreambuf_iterator<E, T>& lhs,
        const istreambuf_iterator<E, T>& rhs);
template<class RanIt, class T, class Ref, class Ptr, class Dist>
    bool operator<(
        const reverse_iterator<RanIt, T, Ref, Ptr, Dist>&mmp lhs,
        const reverse_iterator<RanIt, T, Ref, Ptr, Dist>& rhs);
template<class RanIt, class T, class Ref, class Ptr, class Dist>
    bool operator>(
        const reverse_iterator<RanIt, T, Ref, Ptr, Dist>&mmp lhs,
        const reverse_iterator<RanIt, T, Ref, Ptr, Dist>& rhs);
template<class RanIt, class T, class Ref, class Ptr, class Dist>
    bool operator<=(
        const reverse_iterator<RanIt, T, Ref, Ptr, Dist>&mmp lhs,
        const reverse_iterator<RanIt, T, Ref, Ptr, Dist>& rhs);
template<class RanIt, class T, class Ref, class Ptr, class Dist>
    bool operator>=(
        const reverse_iterator<RanIt, T, Ref, Ptr, Dist>&mmp lhs,
        const reverse_iterator<RanIt, T, Ref, Ptr, Dist>& rhs);
template<class RanIt, class T, class Ref, class Ptr, class Dist>
    Dist operator-(
        const reverse_iterator<RanIt, T, Ref, Ptr, Dist>& lhs,
        const reverse_iterator<RanIt, T, Ref, Ptr, Dist>& rhs);
template<class RanIt, class T, class Ref, class Ptr, class Dist>
    reverse_iterator<RanIt, T, Ref, Ptr, Dist> operator+(
        Dist n,
        const reverse_iterator<RanIt, T, Ref, Ptr, Dist>& rhs);
template<class Cont>
    back_insert_iterator<Cont> back_inserter(Cont& x);
template<class Cont>
    front_insert_iterator<Cont> front_inserter(Cont& x);
template<class Cont, class Iter>
    insert_iterator<Cont> inserter(Cont& x, Iter it);
template<class InIt, class Dist>
    void advance(InIt& it, Dist n);
template<class Init, class Dist>
    ptrdiff_t distance(InIt first, InIt last);
    };

Include the STL standard header <iterator> to define a number of classes, template classes, and template functions that aid in the declaration and manipulation of iterators.


advance

template<class InIt, class Dist>
    void advance(InIt& it, Dist n);

The template function effectively advances it by incrementing it n times. If InIt is a random-access iterator type, the function evaluates the expression it += n. Otherwise, it performs each increment by evaluating ++it. If InIt is an input or forward iterator type, n must not be negative.

See the related sample program.


back_insert_iterator

template<class Cont>
    class back_insert_iterator
        : public iterator<output_iterator_tag, void, void> {
public:
    typedef Cont container_type;
    typedef Cont::value_type value_type;
    explicit back_insert_iterator(Cont& x);
    back_insert_iterator& operator=(const Cont::value_type& val);
    back_insert_iterator& operator*();
    back_insert_iterator& operator++();
    back_insert_iterator operator++(int);
protected:
    Cont& container;
    };

The template class describes an output iterator object. It inserts elements into a container of type Cont, which it accesses via the protected reference object it stores called container. The container must define:

  • The member type value_type, which is the type of an element of the sequence controlled by the container.
  • The member function push_back(value_type c), which appends a new element with value c to the end of the sequence.


back_insert_iterator::back_insert_iterator

explicit back_insert_iterator(Cont& x);

The constructor initializes container with x.


back_insert_iterator::container_type

typedef Cont container_type;

The type is a synonym for the template parameter Cont.


back_insert_iterator::operator*

back_insert_iterator& operator*();

The member function returns *this.


back_insert_iterator::operator++

back_insert_iterator& operator++();
back_insert_iterator operator++(int);

The member functions both return *this.


back_insert_iterator::operator=

back_insert_iterator& operator=(const Cont::value_type& val);

The member function evaluates container . push_back(val), then returns *this.


back_insert_iterator::value_type

typedef Cont::value_type value_type;

The type describes the elements of the sequence controlled by the associated container.


back_inserter

template<class Cont>
    back_insert_iterator<Cont> back_inserter(Cont& x);

The template member function returns back_insert_iterator <Cont>(x).


bidirectional_iterator_tag

struct bidirectional_iterator_tag
    : public forward_iterator_tag {
    };

The type is the same as iterator<It>:: iterator_category when It describes an object that can serve as a bidirectional iterator.


distance

template<class Init, class Dist>
    ptrdiff_t distance(InIt first, InIt last);

The template function sets a count n to zero. It then effectively advances first and increments n until first == last. If InIt is a random-access iterator type, the function evaluates the expression n += last - first. Otherwise, it performs each iterator increment by evaluating ++first.

In this implementation, if a translator does not support partial specialization of templates, the return type is ptrdiff_t instead of iterator_traits<InIt>::distance_type. If you are not certain this type is adequate, use the template function:

template<class InIt, class Dist>
    void _Distance(InIt first, InIt last, Dist& n0);

which adds n to the value stored in n0.

See the related sample program.


forward_iterator_tag

struct forward_iterator_tag
    : public input_iterator_tag {
    };

The type is the same as iterator<It>:: iterator_category when It describes an object that can serve as a forward iterator.


front_insert_iterator

template<class Cont>
    class front_insert_iterator
        : public iterator<output_iterator_tag, void, void> {
public:
    typedef Cont container_type;
    typedef Cont::value_type value_type;
    explicit front_insert_iterator(Cont& x);
    front_insert_iterator& operator=(const Cont::value_type& val);
    front_insert_iterator& operator*();
    front_insert_iterator& operator++();
    front_insert_iterator operator++(int);
protected:
    Cont& container;
    };

The template class describes an output iterator object. It inserts elements into a container of type Cont, which it accesses via the protected reference object it stores called container. The container must define:

  • The member type value_type, which is the type of an element of the sequence controlled by the container.
  • The member function push_front(value_type c), which prepends a new element with value c to the beginning of the sequence.


front_insert_iterator::container_type

typedef Cont container_type;

The type is a synonym for the template parameter Cont.


front_insert_iterator::front_insert_iterator

explicit front_insert_iterator(Cont& x);

The constructor initializes container with x.


front_insert_iterator::operator*

front_insert_iterator& operator*();

The member function returns *this.


front_insert_iterator::operator++

front_insert_iterator& operator++();
front_insert_iterator operator++(int);

The member functions both return *this.


front_insert_iterator::operator=

front_insert_iterator& operator=(const Cont::value_type& val);

The member function evaluates container . push_front(val), then returns *this.


front_insert_iterator::value_type

typedef Cont::value_type value_type;

The type describes the elements of the sequence controlled by the associated container.


front_inserter

template<class Cont>
    front_insert_iterator<Cont> front_inserter(Cont& x);

The template member function returns front_insert_iterator <Cont>(x).


input_iterator_tag

struct input_iterator_tag {
    };

The type is the same as iterator<It>:: iterator_category when It describes an object that can serve as an input iterator.


insert_iterator

template<class Cont>
    class insert_iterator
        : public iterator<output_iterator_tag, void, void> {
public:
    typedef Cont container_type;
    typedef Cont::value_type value_type;
    explicit insert_iterator(Cont& x, Cont::iterator it);
    insert_iterator& operator=(const Cont::value_type& val);
    insert_iterator& operator*();
    insert_iterator& operator++();
    insert_iterator& operator++(int);
protected:
    Cont& container;
    Cont::iterator iter;
    };

The template class describes an output iterator object. It inserts elements into a container of type Cont, which it accesses via the protected reference object it stores called container. It also stores the protected iterator object, of class Cont::iterator, called iter. The container must define:

  • The member type iterator, which is the type of an iterator for the container.
  • The member type value_type, which is the type of an element of the sequence controlled by the container.
  • The member function insert(iterator it, value_type c), which inserts a new element with value c immediately before the element designated by it in the controlled sequence, then returns an iterator that designates the inserted element.


insert_iterator::container_type

typedef Cont container_type;

The type is a synonym for the template parameter Cont.


insert_iterator::insert_iterator

explicit insert_iterator(Cont& x, Cont::iterator it);

The constructor initializes container with x, and iter with it.


insert_iterator::operator*

insert_iterator& operator*();

The member function returns *this.


insert_iterator::operator++

insert_iterator& operator++();
insert_iterator& operator++(int);

The member functions both return *this.


insert_iterator::operator=

insert_iterator& operator=(const Cont::value_type& val);

The member function evaluates iter = container . insert(iter, val), then returns *this.


insert_iterator::value_type

typedef Cont::value_type value_type;

The type describes the elements of the sequence controlled by the associated container.


inserter

template<class Cont, class Iter>
    insert_iterator<Cont> inserter(Cont& x, Iter it);

The template member function returns insert_iterator <Cont>(x, it).


istream_iterator

template<class U, class E = char, class T = char_traits<E> >
    class istream_iterator
        : public iterator<input_iterator_tag, U, ptrdiff_t> {
public:
    typedef E char_type;
    typedef T traits_type;
    typedef basic_istream<E, T> istream_type;
    istream_iterator();
    istream_iterator(istream_type& is);
    const U& operator*() const;
    const U *operator->() const;
    istream_iterator<U, E, T>& operator++();
    istream_iterator<U, E, T> operator++(int);
    };

The template class describes an input iterator object. It extracts objects of class U from an input stream, which it accesses via an object it stores, of type pointer to basic_istream<E, T>. After constructing or incrementing an object of class istream_iterator with a non-null stored pointer, the object attempts to extract and store an object of type U from the associated input stream. If the extraction fails, the object effectively replaces the stored pointer with a null pointer (thus making an end-of-sequence indicator).


istream_iterator::char_type

typedef E char_type;

The type is a synonym for the template parameter E.


istream_iterator::istream_iterator

istream_iterator();
istream_iterator(istream_type& is);

The first constructor initializes the input stream pointer with a null pointer. The second constructor initializes the input stream pointer with &is, then attempts to extract and store an object of type U.


istream_iterator::istream_type

typedef basic_istream<E, T> istream_type;

The type is a synonym for basic_istream<E, T>.


istream_iterator::operator*

const U& operator*() const;

The operator returns the stored object of type U.


istream_iterator::operator->

const U *operator->() const;

The operator returns &**this.


istream_iterator::operator++

istream_iterator<U, E, T>& operator++();
istream_iterator<U, E, T> operator++(int);

The first operator attempts to extract and store an object of type U from the associated input stream. The second operator makes a copy of the object, increments the object, then returns the copy.


istream_iterator::traits_type

typedef T traits_type;

The type is a synonym for the template parameter T.


istreambuf_iterator

template<class E, class T = char_traits<E> >
    class istreambuf_iterator
        : public iterator<input_iterator_tag, T, Dist> {
public:
    typedef E char_type;
    typedef T traits_type;
    typedef T::int_type int_type;
    typedef basic_streambuf<E, T> streambuf_type;

    typedef basic_istream<E, T> istream_type;
    istreambuf_iterator(streambuf_type *sb = 0) throw();
    istreambuf_iterator(istream_type& is) throw();
    const E& operator*() const;
    const E *operator->();
    istreambuf_iterator& operator++();
    istreambuf_iterator operator++(int);
    bool equal(const istreambuf_iterator& rhs);
    };

The template class describes an input iterator object. It extracts elements of class E from an input stream buffer, which it accesses via an object it stores, of type pointer to basic_streambuf<E, T>. After constructing or incrementing an object of class istreambuf_iterator with a non-null stored pointer, the object effectively attempts to extract and store an object of type E from the associated itput stream. (The extraction may be delayed, however, until the object is actually dereferenced or copied.) If the extraction fails, the object effectively replaces the stored pointer with a null pointer (thus making an end-of-sequence indicator).


istreambuf_iterator::char_type

typedef E char_type;

The type is a synonym for the template parameter E.


istreambuf_iterator::equal

bool equal(const istreambuf_iterator& rhs);

The member function returns true only if the stored stream-buffer pointers for the object and rhs are both null pointers or are both non-null pointers.


istreambuf_iterator::int_type

typedef T:int_type int_type;

The type is a synonym for T::int_type">int_type.


istreambuf_iterator::istream_type

typedef basic_istream<E, T> istream_type;

The type is a synonym for basic_istream<E, T>.


istreambuf_iterator::istreambuf_iterator

istreambuf_iterator(streambuf_type *sb = 0) throw();
istreambuf_iterator(istream_type& is) throw();

The first constructor initializes the input stream-buffer pointer with sb. The second constructor initializes the input stream-buffer pointer with is.rdbuf(), then (eventually) attempts to extract and store an object of type E.


istreambuf_iterator::operator*

const E& operator*() const;

The operator returns the stored object of type E.


istreambuf_iterator::operator++

istreambuf_iterator& operator++();
istreambuf_iterator operator++(int);

The first operator (eventually) attempts to extract and store an object of type E from the associated input stream. The second operator makes a copy of the object, increments the object, then returns the copy.


istreambuf_iterator::operator->

const E *operator->() const;

The operator returns &**this.


istreambuf_iterator::streambuf_type

typedef basic_streambuf<E, T> streambuf_type;

The type is a synonym for basic_streambuf<E, T>.


istreambuf_iterator::traits_type

typedef T traits_type;

The type is a synonym for the template parameter T.


iterator

template<class C, class T, class Dist = ptrdiff_t>
    struct iterator {
    typedef C iterator_category;
    typedef T value_type;
    typedef Dist distance_type;
    };

The template class serves as a base type for all iterators. It defines the member types iterator_category (a synonym for the template parameter C), value_type (a synonym for the template parameter T), and distance_type (a synonym for the template parameter Dist).


iterator_traits

template<class It>
    struct iterator_traits {
    typedef It::iterator_category iterator_category;
    typedef It::value_type value_type;
    typedef It::distance_type distance_type;
    };

The template class determines several critical types associated with the iterator type It. It defines the member types iterator_category (a synonym for It::iterator_category), value_type (a synonym for It::value_type), and distance_type (a synonym for It::distance_type).

In this implementation, if a translator does not support partial specialization of templates, you should use the template functions:

template<class C, class T, class Dist>
    C _Iter_cat(const iterator<C, T, Dist>&);
template<class T>
    random_access_iterator_tag _Iter_cat(const T *);

template<class C, class T, class Dist>
    T *_Val_type(const iterator<C, T, Dist>&);
template<class T>
    T *_Val_type(const T *);

template<class C, class T, class Dist>
    Dist *_Dist_type(const iterator<C, T, Dist>&);
template<class T>
    ptrdiff_t *_Dist_type(const T *);

which determine the same types somewhat less directly. You use these functions as arguments on a function call. Their sole purpose is to supply a useful template class parameter to the called function.


operator!=

template<class BidIt, class T, class Ref, class Ptr, class Dist>
    bool operator!=(
        const reverse_bidirectional_iterator<BidIt, T, Ref,
            Ptr, Dist>& lhs,
        const reverse_bidirectional_iterator<BidIt, T, Ref,
            Ptr, Dist>& rhs);
template<class RanIt, class T, class Ref, class Ptr, class Dist>
    bool operator!=(
        const reverse_iterator<BidIt, T, Ref, Ptr, Dist>& lhs,
        const reverse_iterator<BidIt, T, Ref, Ptr, Dist>& rhs);
template<class T, class Dist>
    bool operator!=(
        const istream_iterator<T, Dist>& lhs,
        const istream_iterator<T, Dist>& rhs);
template<class E, class T>
    bool operator!=(
        const istreambuf_iterator<E, T>& lhs,
        const istreambuf_iterator<E, T>& rhs);

The template operator returns !(lhs == rhs).


operator==

template<class BidIt, class T, class Ref, class Ptr, class Dist>
    bool operator==(
        const reverse_bidirectional_iterator<BidIt, T, Ref,
            Ptr, Dist>& lhs,
        const reverse_bidirectional_iterator<BidIt, T, Ref,
            Ptr, Dist>& rhs);
template<class RanIt, class T, class Ref, class Ptr, class Dist>
    bool operator==(
        const reverse_iterator<BidIt, T, Ref, Ptr, Dist>& lhs,
        const reverse_iterator<BidIt, T, Ref, Ptr, Dist>& rhs);
template<class T, class Dist>
    bool operator==(
        const istream_iterator<T, Dist>& lhs,
        const istream_iterator<T, Dist>& rhs);
template<class E, class T>
    bool operator==(
        const istreambuf_iterator<E, T>& lhs,
        const istreambuf_iterator<E, T>& rhs);

The first two template operators each return true only if lhs. current == rhs.current. The third template operator returns true only if both lhs and rhs store the same stream pointer. The fourth template operator returns lhs. equal (rhs).


operator<

template<class RanIt, class T, class Ref, class Ptr, class Dist>
    bool operator<(
        const reverse_iterator<RanIt, T, Ref, Ptr, Dist>& lhs,
        const reverse_iterator<RanIt, T, Ref, Ptr, Dist>& rhs);

The template operator returns rhs. current < lhs.current.


operator<=

template<class RanIt, class T, class Ref, class Ptr, class Dist>
    bool operator<=(
        const reverse_iterator<RanIt, T, Ref, Ptr, Dist>& lhs,
        const reverse_iterator<RanIt, T, Ref, Ptr, Dist>& rhs);

The template operator returns !(rhs < lhs).


operator>

template<class RanIt, class T, class Ref, class Ptr, class Dist>
    bool operator>(
        const reverse_iterator<RanIt, T, Ref, Ptr, Dist>& lhs,
        const reverse_iterator<RanIt, T, Ref, Ptr, Dist>& rhs);

The template operator returns rhs < lhs.


operator>=

template<class RanIt, class T, class Ref, class Ptr, class Dist>
    bool operator>=(
        const reverse_iterator<RanIt, T, Ref, Ptr, Dist>& lhs,
        const reverse_iterator<RanIt, T, Ref, Ptr, Dist>& rhs);

The template operator returns !(lhs < rhs).


operator+

template<class RanIt, class T, class Ref, class Ptr, class Dist>
    reverse_iterator<RanIt, T, Ref, Ptr, Dist> operator+(
        Dist n,
        const reverse_iterator<RanIt, T, Ref, Ptr, Dist>& rhs);

The template operator returns rhs + n.


operator-

template<class RanIt, class T, class Ref, class Ptr, class Dist>
    Dist operator-(
        const reverse_iterator<RanIt, T, Ref, Ptr, Dist>& lhs,
        const reverse_iterator<RanIt, T, Ref, Ptr, Dist>& rhs);

The template operator returns rhs. current - lhs.current.


ostream_iterator

template<class U, class E=char, class Tr=char_traits<E> >
    class ostream_iterator
        : public iterator<output_iterator_tag, void, void> {
public:
    typedef U value_type;
    typedef E char_type;
    typedef T traits_type;
    typedef basic_ostream<E, T> ostream_type;
    ostream_iterator(ostream_type& os);
    ostream_iterator(ostream_type& os, const E *delim);
    ostream_iterator<U, E, T>& operator=(const U& val);
    ostream_iterator<U, E, T>& operator*();
    ostream_iterator<U, E, T>& operator++();
    ostream_iterator<U, E, T> operator++(int);
    };

The template class describes an output iterator object. It inserts objects of class U into an output stream, which it accesses via an object it stores, of type pointer to basic_ostream<E, T>. It also stores a pointer to a delimiter string, a null-terminated string of elements of type E, which is appended after each insertion. (Note that the string itself is not copied by the constructor.)


ostream_iterator::char_type

typedef E char_type;

The type is a synonym for the template parameter E.


ostream_iterator::operator*

ostream_iterator<U, E, T>& operator*();

The operator returns *this.


ostream_iterator::operator++

ostream_iterator<U, E, T>& operator++();
ostream_iterator<U, E, T> operator++(int);

The operators both return *this.


ostream_iterator::operator=

ostream_iterator<U, E, T>& operator=(const U& val);

The operator inserts val into the output stream associated with the object, then returns *this.


ostream_iterator::ostream_iterator

ostream_iterator(ostream_type& os);
ostream_iterator(ostream_type& os, const E *delim);

The first constructor initializes the output stream pointer with &os. The delimiter string pointer designates an empty string. The second constructor initializes the output stream pointer with &os and the delimiter string pointer with delim.


ostream_iterator::ostream_type

typedef basic_ostream<E, T> ostream_type;

The type is a synonym for basic_ostream<E, T>.


ostream_iterator::traits_type

typedef T traits_type;

The type is a synonym for the template parameter T.


ostream_iterator::value_type

typedef U value_type;

The type is a synonym for the template parameter U.


ostreambuf_iterator

template<class E, class T = char_traits<E> >
    class ostreambuf_iterator
        : public iterator<output_iterator_tag, void, void> {
public:
    typedef E char_type;
    typedef T traits_type;
    typedef basic_streambuf<E, T> streambuf_type;
    typedef basic_ostream<E, T> ostream_type;
    ostreambuf_iterator(streambuf_type *sb) throw();
    ostreambuf_iterator(ostream_type& os) throw();
    ostreambuf_iterator& operator=(E x);
    ostreambuf_iterator& operator*();
    ostreambuf_iterator& operator++();
    T1 operator++(int);
    bool failed() const throw();
    };

The template class describes an output iterator object. It inserts elements of class E into an output stream buffer, which it accesses via an object it stores, of type pointer to basic_streambuf<E, T>.


ostreambuf_iterator::char_type

typedef E char_type;

The type is a synonym for the template parameter E.


ostreambuf_iterator::failed

bool failed() const throw();

The member function returns true only if no insertion into the output stream buffer has failed earlier.


ostreambuf_iterator::operator*

ostreambuf_iterator& operator*();

The operator returns *this.


ostreambuf_iterator::operator++

ostreambuf_iterator& operator++();
T1 operator++(int);

The first operator returns *this. The second operator returns an object of some type T1 that can be converted to ostreambuf_iterator<E, T>.


ostreambuf_iterator::operator=

ostreambuf_iterator& operator=(E x);

The operator inserts x into the associated stream buffer, then returns *this.


ostreambuf_iterator::ostream_type

typedef basic_ostream<E, T> ostream_type;

The type is a synonym for basic_ostream<E, T>.


ostreambuf_iterator::ostreambuf_iterator

ostreambuf_iterator(streambuf_type *sb) throw();
ostreambuf_iterator(ostream_type& is) throw();

The first constructor initializes the output stream-buffer pointer with sb. The second constructor initializes the output stream-buffer pointer with is.rdbuf(). (The stored pointer must not be a null pointer.)


ostreambuf_iterator::streambuf_type

typedef basic_streambuf<E, T> streambuf_type;

The type is a synonym for basic_streambuf<E, T>.


ostreambuf_iterator::traits_type

typedef T traits_type;

The type is a synonym for the template parameter T.


output_iterator_tag

struct output_iterator_tag {
    };

The type is the same as iterator<It>:: iterator_category when It describes an object that can serve as an output iterator.


random_access_iterator_tag

struct random_access_iterator_tag
    : public bidirectional_iterator_tag {
    };

The type is the same as iterator<It>:: iterator_category when It describes an object that can serve as a random-access iterator.


reverse_bidirectional_iterator

template<class BidIt,
    class T = iterator_traits<BidIt>::value_type,
    class Ref = T&,
    class Ptr = T *, class Dist = ptrdiff_t>
    class reverse_bidirectional_iterator
        : public iterator<bidirectional_iterator_tag, T, Dist> {
public:
    typedef BidIt iter_type;
    typedef Ref reference_type;
    typedef Ptr pointer_type;
    reverse_bidirectional_iterator();
    explicit reverse_bidirectional_iterator(BidIt x);
    BidIt base() const;
    Ref operator*() const;
    Ptr operator->() const;
    reverse_bidirectional_iterator& operator++();
    reverse_bidirectional_iterator operator++(int);
    reverse_bidirectional_iterator& operator--();
    reverse_bidirectional_iterator operator--();
protected:
    BidIt current;
    };

The template class describes an object that behaves like a bidirectional iterator of class iterator <bidirectional_iterator_tag, T, Dist>. It stores a bidirectional iterator of type BidIt in the protected object current. Incrementing the object x of type reverse_bidirectional_iterator decrements x.current, and decrementing x increments x.current. Moreover, the expression *x evaluates to *--(tmp = current) (where tmp is a temporary object of class BidIt), of type Ref. Typically, Ref is type T&.

Thus, you can use an object of class reverse_bidirectional_iterator to access in reverse order a sequence that is traversed in order by a bidirectional iterator.


reverse_bidirectional_iterator::base

BidIt base() const;

The member function returns current.


reverse_bidirectional_iterator::iter_type

typedef BidIt iter_type;

The type is a synonym for the template parameter BidIt.


reverse_bidirectional_iterator::operator*

Ref operator*() const;

The operator assigns current to a temporary object tmp of class BidIt, then returns *--tmp.


reverse_bidirectional_iterator::operator++

reverse_bidirectional_iterator& operator++();
reverse_bidirectional_iterator operator++(int);

The first (preincrement) operator evaluates -- current. then returns *this.

The second (postincrement) operator makes a copy of *this, evaluates --current, then returns the copy.


reverse_bidirectional_iterator::operator--

reverse_bidirectional_iterator& operator--();
reverse_bidirectional_iterator operator--();

The first (predecrement) operator evaluates ++ current, then returns *this.

The second (postdecrement) operator makes a copy of *this, evaluates ++current, then returns the copy.


reverse_bidirectional_iterator::operator->

Ptr operator->() const;

The operator returns &**this.


reverse_bidirectional_iterator::pointer_type

typedef Ptr pointer_type;

The type is a synonym for the template parameter Ref.


reverse_bidirectional_iterator::reference_type

typedef Ref reference_type;

The type is a synonym for the template parameter Ref.


reverse_bidirectional_iterator::reverse_bidirectional_iterator

reverse_bidirectional_iterator();
explicit reverse_bidirectional_iterator(BidIt x);

The first constructor initializes current with its default constructor. The second constructor initializes current with current(x).


reverse_iterator

template<class RanIt,
    class T = iterator_traits<RanIt>::value_type,
    class Ref = T&,
    class Ptr = T *, class Dist = ptrdiff_t>
    class reverse_iterator
        : public iterator<random_access_iterator_tag, T, Dist> {
public:
    typedef RanIt iter_type;
    typedef Ref reference_type;
    typedef Ptr pointer_type;
    reverse_iterator();
    explicit reverse_iterator(RanIt x);
    RanIt base() const;
    Ref operator*() const;
    Ptr operator->() const;
    reverse_iterator& operator++();
    reverse_iterator operator++(int);
    reverse_iterator& operator--();
    reverse_iterator operator--();
    reverse_iterator& operator+=(Dist n);
    reverse_iterator operator+(Dist n) const;
    reverse_iterator& operator-=(Dist n);
    reverse_iterator operator-(Dist n) const;
    Ref operator[](Dist n) const;
protected:
    RanIt current;
    };

The template class describes an object that behaves like a random-access iterator of class iterator <random_access_iterator_tag, T, Dist>. It stores a random-access iterator of type RanIt in the protected object current. Incrementing the object x of type reverse_iterator decrements x.current, and decrementing x increments x.current. Moreover, the expression *x evaluates to *(current - 1), of type Ref. Typically, Ref is type T&.

Thus, you can use an object of class reverse_iterator to access in reverse order a sequence that is traversed in order by a random-access iterator.


reverse_iterator::base

RanIt base() const;

The member function returns current.


reverse_iterator::iter_type

typedef RanIt iter_type;

The type is a synonym for the template parameter RanIt.


reverse_iterator::operator*

Ref operator*() const;

The operator returns *( current - 1).


reverse_iterator::operator+

reverse_iterator operator+(Dist n) const;

The operator returns reverse_iterator(*this) += n.


reverse_iterator::operator++

reverse_iterator& operator++();
reverse_iterator operator++(int);

The first (preincrement) operator evaluates -- current, then returns *this.

The second (postincrement) operator makes a copy of *this, evaluates --current, then returns the copy.


reverse_iterator::operator+=

reverse_iterator& operator+=(Dist n);

The operator evaluates current - n, then returns *this.


reverse_iterator::operator-

reverse_iterator operator-(Dist n) const;

The operator returns reverse_iterator(*this) -= n.


reverse_iterator::operator--

reverse_iterator& operator--();
reverse_iterator operator--();

The first (predecrement) operator evaluates ++ current, then returns *this.

The second (postdecrement) operator makes a copy of *this, evaluates ++current, then returns the copy.


reverse_iterator::operator-=

reverse_iterator& operator-=(Dist n);

The operator evaluates current + n, then returns *this.


reverse_iterator::operator->

Ptr operator->() const;

The operator returns &**this.


reverse_iterator::operator[]

Ref operator[](Dist n) const;

The operator returns *(*this + n).


reverse_iterator::pointer_type

typedef Ptr pointer_type;

The type is a synonym for the template parameter Ref.


reverse_iterator::reference_type

typedef Ref reference_type;

The type is a synonym for the template parameter Ref.


reverse_iterator::reverse_iterator

reverse_iterator();
explicit reverse_iterator(RanIt x);

The first constructor initializes current with its default constructor. The second constructor initializes current with current(x).


 <limits>

<limits>

namespace std {
    enum float_round_style;
    template<class T>
        class numeric_limits;
    };

Include the standard header <limits> to define the template class numeric_limits. Explicit specializations of this class describe many arithmetic properties of the scalar types (other than pointers).


float_round_style

enum float_round_style {
    round_indeterminate = -1,
    round_toward_zero = 0,
    round_to_nearest = 1,
    round_toward_infinity = 2,
    round_toward_neg_infinity = 3
    };

The enumeration describes the various methods that an implementation can choose for rounding a floating-point value to an integer value:

  • round_indeterminate -- rounding method cannot be determined
  • round_toward_zero -- round toward zero
  • round_to_nearest -- round to nearest integer
  • round_toward_infinity -- round away from zero
  • round_toward_neg_infinity -- round to more negative integer


numeric_limits

template<class T>
    class numeric_limits {
public:
    static const bool has_denorm = false;
    static const bool has_denorm_loss = false;
    static const bool has_infinity = false;
    static const bool has_quiet_NaN = false;
    static const bool has_signaling_NaN = false;
    static const bool is_bounded = false;
    static const bool is_exact = false;
    static const bool is_iec559 = false;
    static const bool is_integer = false;
    static const bool is_modulo = false;
    static const bool is_signed = false;
    static const bool is_specialized = false;
    static const bool tinyness_before = false;
    static const bool traps = false;
    static const float_round_style round_style = round_toward_zero;
    static const int digits = 0;
    static const int digits10 = 0;
    static const int max_exponent = 0;
    static const int max_exponent10 = 0;
    static const int min_exponent = 0;
    static const int min_exponent10 = 0;
    static const int radix = 0;
    static T denorm_min() throw();
    static T epsilon() throw();
    static T infinity() throw();
    static T max() throw();
    static T min() throw();
    static T quiet_NaN() throw();
    static T round_error() throw();
    static T signaling_NaN() throw();
    };

The template class describes many arithmetic properties of its parameter type T. The header defines explicit specializations for the types wchar_t, bool, char, signed char, unsigned char, short, unsigned short, int, unsigned int, long, unsigned long, float, double, and long double. For all these explicit specializations, the member is_specialized is true, and all relevant members have meaningful values. The program can supply additional explicit specializations.

For an arbitrary specialization, no members have meaningful values. A member object that does not have a meaningful value stores zero (or false) and a member function that does not return a meaningful value returns T(0).

See the related numeric_limits sample program.


numeric_limits::denorm_min

static T denorm_min() throw();

The function returns the minimum value for the type (which is the same as min() if has_denorm is false).

See the related numeric_limits sample program.


numeric_limits::digits

static const int digits = 0;

The member stores the number of radix digits that the type can represent without change (which is the number of bits other than any sign bit for a predefined integer type, or the number of mantissa digits for a predefined floating-point type).

See the related numeric_limits sample program.


numeric_limits::digits10

static const int digits10 = 0;

The member stores the number of decimal digits that the type can represent without change.

See the related numeric_limits sample program.


numeric_limits::epsilon

static T epsilon() throw();

The function returns the difference between 1 and the smallest value greater than 1 that is representable for the type (which is the value FLT_EPSILON for type float).

See the related numeric_limits sample program.


numeric_limits::has_denorm

static const bool has_denorm = false;

The member stores true for a floating-point type that has denormalized values (effectively a variable number of exponent bits).

See the related numeric_limits sample program.


numeric_limits::has_denorm_loss

static const bool has_denorm_loss = false;

The member stores true for a type that determines whether a value has lost accuracy because it is delivered as a denormalized result (too small to represent as a normalized value) or because it is inexact (not the same as a result not subject to limitations of exponent range and precision). The latter is an option with IEC 559 floating-point representations that can affect some results.

See the related numeric_limits sample program.


numeric_limits::has_infinity

static const bool has_infinity = false;

The member stores true for a type that has a representation for positive infinity. True if is_iec559 is true.

See the related numeric_limits sample program.


numeric_limits::has_quiet_NaN

static const bool has_quiet_NaN = false;

The member stores true for a type that has a representation for a quiet NaN, an encoding that is "Not a Number" that does not signal its presence in an expression. True if is_iec559 is true.

See the related numeric_limits sample program.


numeric_limits::has_signaling_NaN

static const bool has_signaling_NaN = false;

The member stores tree for a type that has a representation for a signaling NaN, an encoding that is ``Not a Number'' which signals its presence in an expression by reporting an exception. True if is_iec559 is true.

See the related numeric_limits sample program.


numeric_limits::infinity

static T infinity() throw();

The function returns the representation of positive infinity for the type. The return value is meaningful only if has_infinity is true.

See the related numeric_limits sample program.


numeric_limits::is_bounded

static const bool is_bounded = false;

The member stores true for a type that has a bounded set of representable values (which is the case for all predefined types).

See the related numeric_limits sample program.


numeric_limits::is_exact

static const bool is_exact = false;

The member stores true for a type that has exact representations for all its values (which is the case for all predefined integer types). A fixed-point or rational representation is also considered exact, but not a floating-point representation.

See the related numeric_limits sample program.


numeric_limits::is_iec559

static const bool is_iec559 = false;

The member stores true for a type that has a representation conforming to IEC 559, an international standard for representing floating-point values (also known as IEEE 754 in the United States).

See the related numeric_limits sample program.


numeric_limits::is_integer

static const bool is_integer = false;

The member stores true for a type that has an integer representation (which is the case for all predefined integer types).

See the related numeric_limits sample program.


numeric_limits::is_modulo

static const bool is_modulo = false;

The member stores true for a type that has a modulo representation, where all results are reduced modulo some value (which is the case for all predefined unsigned integer types).

See the related numeric_limits sample program.


numeric_limits::is_signed

static const bool is_signed = false;

The member stores true for a type that has a signed representation (which is the case for all predefined floating-point and signed integer types).

See the related numeric_limits sample program.


numeric_limits::is_specialized

static const bool is_specialized = false;

The member stores true for a type that has an explicit specialization defined for template class numeric_limits (which is the case for all scalar types other than pointers).

See the related numeric_limits sample program.


numeric_limits::max

static T max() throw();

The function returns the maximum finite value for the type (which is INT_MAX for type int and FLT_MAX for type float). The return value is meaningful if is_bounded is true.

See the related numeric_limits sample program.


numeric_limits::max_exponent

static const int max_exponent = 0;

The member stores the maximum positive integer such that the type can represent as a finite value radix raised to that power (which is the value FLT_MAX_EXP for type float). Meaningful only for floating-point types.

See the related numeric_limits sample program.


numeric_limits::max_exponent10

static const int max_exponent10 = 0;

The member stores the maximum positive integer such that the type can represent as a finite value 10 raised to that power (which is the value FLT_MAX_10_EXP for type float). Meaningful only for floating-point types.

See the related numeric_limits sample program.


numeric_limits::min

static T min() throw();

The function returns the minimum normalized value for the type (which is INT_MIN for type int and FLT_MIN for type float). The return value is meaningful if is_bounded is true or is_signed is false.

See the related numeric_limits sample program.


numeric_limits::min_exponent

static const int min_exponent = 0;

The member stores the minimum negative integer such that the type can represent as a normalized value radix raised to that power (which is the value FLT_MIN_EXP for type float). Meaningful only for floating-point types.

See the related numeric_limits sample program.


numeric_limits::min_exponent10

static const int min_exponent10 = 0;

The member stores the minimum negative integer such that the type can represent as a normalized value 10 raised to that power (which is the value FLT_MIN_10_EXP for type float). Meaningful only for floating-point types.

See the related numeric_limits sample program.


numeric_limits::quiet_NaN

static T quiet_NaN() throw();

The function returns a representation of a quiet NaN for the type. The return value is meaningful only if has_quiet_NaN is true.

See the related numeric_limits sample program.


numeric_limits::radix

static const int radix = 0;

The member stores the base of the representation for the type (which is 2 for the predefined integer types, and the base to which the exponent is raised, or FLT_RADIX, for the predefined floating-point types).

See the related numeric_limits sample program.


numeric_limits::round_error

static T round_error() throw();

The function returns the maximum rounding error for the type.

See the related numeric_limits sample program.


numeric_limits::round_style

static const float_round_style round_style = round_toward_zero;

The member stores a value that describes the various methods an implementation can choose for rounding a floating-point value to an integer value.

See the related numeric_limits sample program.


numeric_limits::signaling_NaN

static T signaling_NaN() throw();

The function returns a representation of a signaling NaN for the type. The return value is meaningful only if has_signaling_NaN is true.

See the related numeric_limits sample program.


numeric_limits::tinyness_before

static const bool tinyness_before = false;

The member stores true for a type that determines whether a value is "tiny" (too small to represent as a normalized value) before rounding, an option with IEC 559 floating-point representations that can affect some results.

See the related numeric_limits sample program.


numeric_limits::traps

static const bool traps = false;

The member stores true for a type that generates some kind of signal to report certain arithmetic exceptions.

See the related numeric_limits sample program.


 <list>

<list>

namespace std {
template<class T, class A>
    class list;
//    TEMPLATE FUNCTIONS
template<class T, class A>
    bool operator==(
        const list<T, A>& lhs,
        const list<T, A>& rhs);
template<class T, class A>
    bool operator!=(
        const list<T, A>& lhs,
        const list<T, A>& rhs);
template<class T, class A>
    bool operator<(
        const list<T, A>& lhs,
        const list<T, A>& rhs);
template<class T, class A>
    bool operator>(
        const list<T, A>& lhs,
        const list<T, A>& rhs);
template<class T, class A>
    bool operator<=(
        const list<T, A>& lhs,
        const list<T, A>& rhs);
template<class T, class A>
    bool operator>=(
        const list<T, A>& lhs,
        const list<T, A>& rhs);
template<class T, class A>
    void swap(
        const list<T, A>& lhs,
        const list<T, A>& rhs);
    };

Include the STL standard header <list> to define the container template class list and three supporting templates.


list

allocator_type · assign · back · begin · clear · const_iterator · const_reference · const_reverse_iterator · difference_type · empty · end · erase · front · get_allocator · insert · iterator · list · max_size · merge · pop_back · pop_front · push_back · push_front · rbegin · reference · remove · remove_if · rend · resize · reverse · reverse_iterator · size · size_type · sort · splice · swap · unique · value_type

template<class T, class A = allocator<T> >
    class list {
public:
    typedef A allocator_type;
    typedef A::size_type size_type;
    typedef A::difference_type difference_type;
    typedef A::reference reference;
    typedef A::const_reference const_reference;
    typedef A::value_type value_type;
    typedef T0 iterator;
    typedef T1 const_iterator;
    typedef reverse_bidirectional_iterator<iterator,
        value_type, reference, A::pointer,
            difference_type> reverse_iterator;
    typedef reverse_bidirectional_iterator<const_iterator,
        value_type, const_reference, A::const_pointer,
             difference_type> const_reverse_iterator;
    explicit list(const A& al = A());
    explicit list(size_type n, const T& v = T(), const A& al = A());
    list(const list& x);
    list(const_iterator first, const_iterator last,
        const A& al = A());
    iterator begin();
    const_iterator begin() const;
    iterator end();
    iterator end() const;
    reverse_iterator rbegin();
    const_reverse_iterator rbegin() const;
    reverse_iterator rend();
    const_reverse_iterator rend() const;
    void resize(size_type n, T x = T());
    size_type size() const;
    size_type max_size() const;
    bool empty() const;
    A get_allocator() const;
    reference front();
    const_reference front() const;
    reference back();
    const_reference back() const;
    void push_front(const T& x);
    void pop_front();
    void push_back(const T& x);
    void pop_back();
    void assign(const_iterator first, const_iterator last);
    void assign(size_type n, const T& x = T());
    iterator insert(iterator it, const T& x = T());
    void insert(iterator it, size_type n, const T& x);
    void insert(iterator it,
        const_iterator first, const_iterator last);
    void insert(iterator it,
        const T *first, const T *last);
    iterator erase(iterator it);
    iterator erase(iterator first, iterator last);
    void clear();
    void swap(list x);
    void splice(iterator it, list& x);
    void splice(iterator it, list& x, iterator first);
    void splice(iterator it, list& x, iterator first, iterator last);
    void remove(const T& x);
    void remove_if(binder2nd<not_equal_to<T> > pr);
    void unique();
    void unique(not_equal_to<T> pr);
    void merge(list& x);
    void merge(list& x, greater<T> pr);
    void sort();
    template<class Pred>
        void sort(greater<T> pr);
    void reverse();
protected:
    A allocator;
    };

The template class describes an object that controls a varying-length sequence of elements of type T. The sequence is stored as a bidirectional linked list of elements, each containing a member of type T.

The object allocates and frees storage for the sequence it controls through a protected object named allocator, of class A. Such an allocator object must have the same external interface as an object of template class allocator. Note that allocator is not copied when the object is assigned.

List reallocation occurs when a member function must insert or erase elements of the controlled sequence. In all such cases, only iterators or references that point at erased portions of the controlled sequence become invalid.


list::allocator_type

typedef A allocator_type;

The type is a synonym for the template parameter A.


list::assign

void assign(const_iterator first, const_iterator last);
void assign(size_type n, const T& x = T());

The first member function replaces the sequence controlled by *this with the sequence [first, last). The second member function replaces the sequence controlled by *this with a repetition of n elements of value x.

In this implementation, if a translator does not support member template functions, the templates:

template<class InIt>
    void assign(InIt first, InIt last);
template<class Size, class T2>
    void assign(Size n, const T2& x = T2());

are replaced by:

void assign(const_iterator first, const_iterator last);
void assign(size_type n, const T& x = T());

See the related sample program.


list::back

reference back();
const_reference back() const;

The member function returns a reference to the last element of the controlled sequence, which must be non-empty.

See the related sample program.


list::begin

const_iterator begin() const;
iterator begin();

The member function returns a bidirectional iterator that points at the first element of the sequence (or just beyond the end of an empty sequence).


list::clear

void clear() const;

The member function calls erase ( begin (), end ()).


list::const_iterator

typedef T1 const_iterator;

The type describes an object that can serve as a constant bidirectional iterator for the controlled sequence. It is described here as a synonym for the unspecified type T1.


list::const_reference

typedef A::const_reference const_reference;

The type describes an object that can serve as a constant reference to an element of the controlled sequence.


list::const_reverse_iterator

typedef reverse_bidirectional_iterator<const_iterator,
    value_type, const_reference, A::const_pointer,
        difference_type> const_reverse_iterator;

The type describes an object that can serve as a constant reverse bidirectional iterator for the controlled sequence.


list::difference_type

typedef A::difference_type difference_type;

The signed integer type describes an object that can represent the difference between the addresses of any two elements in the controlled sequence.


list::empty

bool empty() const;

The member function returns true for an empty controlled sequence.


list::end

const_iterator end() const;
iterator end();

The member function returns a bidirectional iterator that points just beyond the end of the sequence.


list::erase

iterator erase(iterator it);
iterator erase(iterator first, iterator last);

The first member function removes the element of the controlled sequence pointed to by it. The second member function removes the elements of the controlled sequence in the range [first, last). Both return an iterator that designates the first element remaining beyond any elements removed, or end () if no such element exists.

Erasing N elements causes N destructor calls. No reallocation occurs, so iterators and references become invalid only for the erased elements.


list::front

reference front();
const_reference front() const;

The member function returns a reference to the first element of the controlled sequence, which must be non-empty.

See the related sample program.


list::get_allocator

A get_allocator() const;

The member function returns allocator.


list::insert

iterator insert(iterator it, const T& x = T());
void insert(iterator it, size_type n, const T& x);
void insert(iterator it, const_iterator first, const_iterator last);

Each of the member functions inserts, before the element pointed to by it in the controlled sequence, a sequence specified by the remaining operands. The first member function inserts a single element with value x and returns an iterator that points to the newly inserted element. The second member function inserts a repetition of n elements of value x. The last member function inserts the sequence [first, last).

In this implementation, if a translator does not support member template functions, the template:

template<class InIt>
    void insert(iterator it, InIt first, InIt last);

is replaced by:

void insert(iterator it, const_iterator first, const_iterator last);
void insert(iterator it, const T *first, const T *last);

Inserting N elements causes N copies. No reallocation occurs, so no iterators or references become invalid.

See the related sample program.


list::iterator

typedef T0 iterator;

The type describes an object that can serve as a bidirectional iterator for the controlled sequence. It is described here as a synonym for the unspecified type T0.


list::list

explicit list(const A& al = A());
explicit list(size_type n, const T& v = T(), const A& al = A());
list(const list& x);
list(const_iterator first, const_iterator last, const A& al = A());

All constructors store the allocator object al (or, for the copy constructor, x. get_allocator ()) in allocator and initialize the controlled sequence. The first constructor specifies an empty initial controlled sequence. The second constructor specifies a repetition of n elements of value x. The third constructor specifies a copy of the sequence controlled by x. The last constructor specifies the sequence [first, last). None of the constructors perform any interim reallocations.

In this implementation, if a translator does not support member template functions, the template:

template<class InIt>
    list(InIt first, InIt last, const A& al = A());

is replaced by:

list(const_iterator first, const_iterator last,
    const A& al = A());

See the related sample program.


list::max_size

size_type max_size() const;

The member function returns the length of the longest sequence that the object can control.


list::merge

void merge(list& x);
void merge(list& x, greater<T> pr);

Both member functions remove all elements from the sequence controlled by x and insert them into the controlled sequence. Both sequences must be ordered by the same predicate, described below. The resulting sequence is also ordered by that predicate.

For the iterators Pi and Pj designating elements at positions i and j, the first member function imposes the order !(*Pj < *Pi) whenever i < j. (The elements are sorted in ascending order.) The second member function imposes the order !pr(*Pj, *Pi) whenever i < j.

No pairs of elements in the original controlled sequence are reversed in the resulting controlled sequence. If a pair of elements in the resulting controlled sequence compares equal (!(*Pi < *Pj) && !(*Pj < *Pi)), an element from the original controlled sequence appears before an element from the sequence controlled by x.

In this implementation, if a translator does not support member template functions, the template:

template<class Pred>
    void merge(list& x, Pred pr);

is replaced by:

void merge(list& x, greater <T> pr);


list::pop_back

void pop_back();

The member function removes the last element of the controlled sequence, which must be non-empty.


list::push_back

void push_back(const T& x);

The member function inserts an element with value x at the end of the controlled sequence.


list::pop_front

void pop_front();

The member function removes the first element of the controlled sequence, which must be non-empty.


list::push_front

void push_front(const T& x);

The member function inserts an element with value x at the beginning of the controlled sequence.


list::rbegin

const_reverse_iterator rbegin() const;
reverse_iterator rbegin();

The member function returns a reverse bidirectional iterator that points just beyond the end of the controlled sequence. Hence, it designates the beginning of the reverse sequence.


list::reference

typedef A::reference reference;

The type describes an object that can serve as a reference to an element of the controlled sequence.


list::remove

void remove(const T& x);

The member function removes from the controlled sequence all elements, designated by the iterator P, for which *P == x.


list::remove_if

void remove_if(binder2nd<not_equal_to<T> > pr);

The member function removes from the controlled sequence all elements, designated by the iterator P, for which pr(*P) is true.

In this implementation, if a translator does not support member template functions, the template:

templace<class Pred>
    void remove_if(Pred pr);

is replaced by:

>void remove_if( binder2nd < not_equal_to <T> > pr);


list::rend

const_reverse_iterator rend() const;
reverse_iterator rend();

The member function returns a reverse bidirectional iterator that points at the first element of the sequence (or just beyond the end of an empty sequence). Hence, it designates the end of the reverse sequence.


list::resize

void resize(size_type n, T x = T());

The member function ensures that size () henceforth returns n. If it must make the controlled sequence longer, it appends elements with value x.


list::reverse

void reverse();

The member function reverses the order in which elements appear in the controlled sequence.


list::reverse_iterator

typedef reverse_bidirectional_iterator<iterator,
    value_type, reference, A::pointer,
        difference_type> reverse_iterator;

The type describes an object that can serve as a reverse bidirectional iterator for the controlled sequence.


list::size

size_type size() const;

The member function returns the length of the controlled sequence.


list::size_type

typedef A::size_type size_type;

The unsigned integer type describes an object that can represent the length of any controlled sequence.


list::sort

void sort();
template<class Pred>
    void sort(greater<T> pr);

Both member functions order the elements in the controlled sequence by a predicate, described below.

For the iterators Pi and Pj designating elements at positions i and j, the first member function imposes the order !(*Pj < *Pi) whenever i < j. (The elements are sorted in ascending order.) The member template function imposes the order !pr(*Pj, *Pi) whenever i < j. No pairs of elements in the original controlled sequence are reversed in the resulting controlled sequence.

In this implementation, if a translator does not support member template functions, the template:

template<class Pred>
    void sort(Pred pr);

is replaced by:

void sort( greater <T> pr);


list::splice

void splice(iterator it, list& x);
void splice(iterator it, list& x, iterator first);
void splice(iterator it, list& x, iterator first, iterator last);

The first member function inserts the sequence controlled by x before the element in the controlled sequence pointed to by it. It also removes all elements from x. (&x must not equal this.)

The second member function removes the element pointed to by first in the sequence controlled by x and inserts it before the element in the controlled sequence pointed to by it. (If it == first || it == ++first, no change occurs.)

The third member function inserts the subrange designated by [first, last) from the sequence controlled by x before the element in the controlled sequence pointed to by it. It also removes the original subrange from the sequence controlled by x. (If &x == this, the range [first, last) must not include the element pointed to by it.)

If the third member function inserts N elements, and &x != this, an object of class iterator is incremented N times. For all splice member functions, if allocator != str.allocator, a copy and a destructor call also occur for each inserted element.


list::swap

void swap(list& str);

The member function swaps the controlled sequences between *this and str. If allocator == str.allocator, it does so in constant time. Otherwise, it performs a number of element assignments and constructor calls proportional to the number of elements in the two controlled sequences.


list::unique

void unique();
void unique(not_equal_to<T> pr);

The first member function removes from the controlled sequence every element that compares equal to its preceding element. For the iterators Pi and Pj designating elements at positions i and j, the second member function removes every element for which i + 1 == j && pr(*Pi, *Pj).

In this implementation, if a translator does not support member template functions, the template:

template<class Pred>
    void unique(Pred pr);

is replaced by:

void unique( not_equal_to <T> pr);

For a controlled sequence of length N (> 0), the predicate pr(*Pi, *Pj) is evaluated N - 1 times.


list::value_type

typedef A::value_type value_type;

The type is a synonym for the template parameter T.


operator!=

template<class T, class A>
    bool operator!=(
        const list <T, A>& lhs,
        const list <T, A>& rhs);

The template function returns !(lhs == rhs).


operator==

template<class T, class A>
    bool operator==(
        const list <T, A>& lhs,
        const list <T, A>& rhs);

The template function overloads operator== to compare two objects of template class list. The function returns lhs. size () == rhs.size() && equal (lhs. begin (), lhs. end (), rhs.begin()).


operator<

template<class T, class A>
    bool operator<(
        const list <T, A>& lhs,
        const list <T, A>& rhs);

The template function overloads operator< to compare two objects of template class list. The function returns lexicographical_compare (lhs. begin (), lhs. end (), rhs.begin(), rhs.end()).


operator<=

template<class T, class A>
    bool operator<=(
        const list <T, A>& lhs,
        const list <T, A>& rhs);

The template function returns !(rhs < lhs).


operator>

template<class T, class A>
    bool operator>(
        const list <T, A>& lhs,
        const list <T, A>& rhs);

The template function returns rhs < lhs.


operator>=

template<class T, class A>
    bool operator>=(
        const list <T, A>& lhs,
        const list <T, A>& rhs);

The template function returns !(rhs < lhs).


swap

template<class T, class A>
    void swap(
        const list <T, A>& lhs,
        const list <T, A>& rhs);

The template function executes lhs. swap (rhs).


 <locale>

<locale>

codecvt · codecvt_base · codecvt_byname · collate · collate_byname · ctype · ctype<char> · ctype_base · ctype_byname · has_facet · locale · messages · messages_base · messages_byname · money_base · money_get · money_put · moneypunct · moneypunct_byname · num_get · num_put · numpunct · numpunct_byname · time_base · time_get · time_get_byname · time_put · time_put_byname · use_facet

isalnum · isalpha · iscntrl · isdigit · isgraph · islower · isprint · ispunct · isspace · isupper · isxdigit · tolower · toupper

namespace std {
    class locale;
    class ctype_base;
    template<class E>
        class ctype;
    class ctype<char>;
    template<class E>
        class ctype_byname;
    class codecvt_base;
    template<class From, class To, class State>
        class codecvt;
    template<class From, class To, class State>
        class codecvt_byname;
    template<class E, class InIt>
        class num_get;
    template<class E, class OutIt>
        class num_put;
    template<class E>
        class numpunct;
    template<class E>
        class numpunct_byname;
    template<class E>
        class collate;
    template<class E>
        class collate_byname;
    class time_base;
    template<class E, class InIt>
        class time_get;
    template<class E, class InIt>
        class time_get_byname;
    template<class E, class OutIt>
        class time_put;
    template<class E, class OutIt>
        class time_put_byname;
    class money_base;
    template<class E, bool Intl, class InIt>
        class money_get;
    template<class E, bool Intl, class OutIt>
        class money_put;
    template<class E, bool Intl>
        class moneypunct;
    template<class E, bool Intl>
        class moneypunct_byname;
    class messages_base;
    template<class E>
        class messages;
    template<class E>
        class messages_byname;
//    TEMPLATE FUNCTIONS
    template<class Facet>
        bool has_facet(const locale& loc, const Facet *fac);
    template<class Facet>
        const Facet& use_facet(const locale& loc,
            const Facet *fac, bool is_std);
    template<class E>
        bool isspace(E c, const locale& loc) const;
    template<class E>
        bool isprint(E c, const locale& loc) const;
    template<class E>
        bool iscntrl(E c, const locale& loc) const;
    template<class E>
        bool isupper(E c, const locale& loc) const;
    template<class E>
        bool islower(E c, const locale& loc) const;
    template<class E>
        bool isalpha(E c, const locale& loc) const;
    template<class E>
        bool isdigit(E c, const locale& loc) const;
    template<class E>
        bool ispunct(E c, const locale& loc) const;
    template<class E>
        bool isxdigit(E c, const locale& loc) const;
    template<class E>
        bool isalnum(E c, const locale& loc) const;
    template<class E>
        bool isgraph(E c, const locale& loc) const;
    template<class E>
        E toupper(E c, const locale& loc) const;
    template<class E>
        E tolower(E c, const locale& loc) const;
    };

Include the standard header <locale> to define a host of template classes and functions that encapsulate and manipulate locales.


codecvt

template<class From, class To, class State>
    class codecvt : public locale::facet, public codecvt_base {
public:
    typedef From from_type;
    typedef To to_type;
    typedef State state_type;
    explicit codecvt(size_t refs = 0);
    result in(State& state,
        const To *first1, const To *last1, const To *next1,
        From *first2, From *last2, From *next2);
    result out(State& state,
        const From *first1, const From *last1, const From *next1,
        To *first2, To *last2, To *next2);
    bool always_noconv() const throw();
    int max_length() const throw();
    int length(State& state,
        From *first1, const From *last1, size_t _N2) const throw();
    int encoding() const throw();
    static locale::id id;
protected:
    ~codecvt();
    virtual result do_in(State& state,
        const To *first1, const To *last1, const To *next1,
        From *first2, From *last2, From *next2);
    virtual result do_out(State& state,
        const From *first1, const From *last1, const From *next1,
        To *first2, To *last2, To *next2);
    virtual bool do_always_noconv() const throw();
    virtual int do_max_length() const throw();
    virtual int do_encoding() const throw();
    virtual int do_length(State& state,
        From *first1, const From *last1, size_t len2) const throw();
    };

The template class describes an object that can serve as a locale facet, to control conversions between a sequence of values of type From and a sequence of values of type To. The class State characterizes the transformation -- and an object of class State stores any necessary state information during a conversion.

As with any locale facet, the static object id has an initial stored value of zero. The first attempt to access its stored value stores a unique positive value in id.

The template versions of do_in do_out always return codecvt_base:: noconv. The Standard C++ library defines an explicit specialization, however, that is more useful:

codecvt<wchar_t, char, mbstate_t

which converts between wchar_t and char sequences.


codecvt::always_noconv

bool always_noconv() const throw();

The member function returns do_always_noconv ().


codecvt::codecvt

explicit codecvt(size_t refs = 0);

The constructor initializes its locale::facet base object with locale:: facet (refs).


codecvt::do_always_noconv

virtual bool do_always_noconv() const throw();

The protected virtual member function returns true only if every call to do_in or do_out returns noconv. The template version always returns true.


codecvt::do_encoding

virtual int do_encoding() const throw();

The protected virtual member function returns:

  • -1, if the encoding of sequences of type to_type is state dependent
  • 0, if the encoding involves sequences of varying lengths
  • n, if the encoding involves only sequences of length n


codecvt::do_in

virtual result do_in(State state&,
    const To *first1, const To *last1, const To *next1,
    From *first2, From *last2, From *next2);

The protected virtual member function endeavors to convert the source sequence at [first1, last1) to a destination sequence that it stores within [first2, last2). It always stores in next1 a pointer to the first unconverted element in the source sequence, and it always stores in next2 a pointer to the first unaltered element in the destination sequence.

state must represent the initial conversion state at the beginning of a new source sequence. The function alters its stored value, as needed, to reflect the current state of a successful conversion. Its stored value is otherwise unspecified.

The function returns:

  • codecvt_base:: error if the source sequence is ill-formed
  • codecvt_base:: noconv if the function performs no conversion
  • codecvt_base:: ok if the conversion succeeds
  • codecvt_base:: partial if the source is insufficient, or if the destination is not large enough, for the conversion to succeed

The template version always returns noconv.


codecvt::do_length

virtual int do_length(State state&,
    From *first1, const From *last1, size_t len2) const throw();

The protected virtual member function effectively calls do_out (state, first1, last1, next1, buf, buf + len2, next2) for some buffer buf and pointer next2, then returns next2 - buf. (Thus, it is roughly analogous to the function mbrlen, at least when From is type char.)

The template version always returns the lesser of last1 - first1 and len2.


codecvt::do_max_length

virtual int do_max_length() const throw();

The protected virtual member function returns the largest permissible value that can be returned by do_length (first1, last1, 1), for arbitrary valid values of first1 and last1. (Thus, it is roughly analogous to the macro MB_CUR_MAX, at least when From is type char.)

The template version always returns 1.


codecvt::do_out

virtual result do_out(State state&,
    const From *first1, const From *last1, const From *next1,
    To *first2, To *last2, To *next2);

The protected virtual member function endeavors to convert the source sequence at [first1, last1) to a destination sequence that it stores within [first2, last2). It always stores in next1 a pointer to the first unconverted element in the source sequence, and it always stores in next2 a pointer to the first unaltered element in the destination sequence.

state must represent the initial conversion state at the beginning of a new source sequence. The function alters its stored value, as needed, to reflect the current state of a successful conversion. Its stored value is otherwise unspecified.

The function returns:

  • codecvt_base:: error if the source sequence is ill-formed
  • codecvt_base:: noconv if the function performs no conversion
  • codecvt_base:: ok if the conversion succeeds
  • codecvt_base:: partial if the source is insufficient, or if the destination is not large enough, for the conversion to succeed

The template version always returns noconv.


codecvt::encoding

int encoding() const throw();

The member function returns do_encoding ().


codecvt::from_type

typedef From from_type;

The type is a synonym for the template parameter From.


codecvt::in

result in(State state&,
    const To *first1, const To *last1, const To *next1,
    From *first2, From *last2, From *next2);

The member function returns do_in (state, first1, last1, next1, first2, last2, next2).


codecvt::length

int length(State state&,
    From *first1, const From *last1, size_t len2) const throw();

The member function returns do_length (first1, last1, len2).


codecvt::max_length

int max_length() const throw();

The member function returns do_max_length ().


codecvt::out

result out(State state&,
    const From *first1, const From *last1, const From *next1,
    To *first2, To *last2, To *next2);

The member function returns do_out (state, first1, last1, next1, first2, last2, next2).


codecvt::state_type

typedef State state_type;

The type is a synonym for the template parameter State.


codecvt::to_type

typedef To to_type;

The type is a synonym for the template parameter To.


codecvt_base

class codecvt_base {
public:
    enum result {ok, partial, error, noconv};
    };

The class describes an enumeration common to all specializations of template class codecvt. The enumeration result describes the possible return values from do_in or do_out:

  • error if the source sequence is ill-formed
  • noconv if the function performs no conversion
  • ok if the conversion succeeds
  • partial if the destination is not large enough for the conversion to succeed


codecvt_byname

template<class From, class To, class State>
    class codecvt_byname : public codecvt<From, To, State> {
public:
    explicit codecvt_byname(const char *s, size_t refs = 0);
protected:
    ~codecvt_byname();
    };

The template class describes an object that can serve as a locale facet of type codecvt <From, To, State>. Its behavior is determined by the named locale s. The constructor initializes its base object with codecvt <From, To, State>(refs).


collate

template<class E>
    class collate : public locale::facet {
public:
    typedef E char_type;
    typedef basic_string<E> string_type;
    explicit collate(size_t refs = 0);
    int compare(const E *first1, const E *last1,
        const E *first2, const E *last2) const;
    string_type transform(const E *first, const E *last) const;
    long hash(const E *first, const E *last) const;
    static locale::id id;
protected:
    ~collate();
    virtual int do_compare(const E *first1, const E *last1,
        const E *first2, const E *last2) const;
    virtual string_type do_transform(const E *first, const E *last) const;
    virtual long do_hash(const E *first, const E *last) const;
    };

The template class describes an object that can serve as a locale facet, to control comparisons of sequences of type E.

As with any locale facet, the static object id has an initial stored value of zero. The first attempt to access its stored value stores a unique positive value in id.


collate::char_type

typedef E char_type;

The type is a synonym for the template parameter E.


collate::collate

explicit collate(size_t refs = 0);

The constructor initializes its base object with locale:: facet (refs).


collate::compare

int compare(const E *first1, const E *last1,
    const E *first2, const E *last2) const;

The member function returns do_compare (first1, last1, first2, last2).


collate::do_compare

virtual int do_compare(const E *first1, const E *last1,
    const E *first2, const E *last2) const;

The protected virtual member function compares the sequence at [first1, last1) with the sequence at [first2, last2). It compares values by applying operator< between pairs of corresponding elements of type E. The first sequence compares less if it has the smaller element in the earliest unequal pair in the sequences, or if no unequal pairs exist but the first sequence is shorter.

If the first sequence compares less than the second sequence, the function returns -1. If the second sequence compares less, the function returns +1. Otherwise, the function returns zero.


collate::do_transform

virtual string_type do_transform(const E *first, const E *last) const;

The protected virtual member function returns an object of class string_type whose controlled sequence is a copy of the sequence [first, last). If a class derived from collate<E> overrides do_compare, it should also override do_transform to match. Put simply, two transformed strings should yield the same result, when passed to collate::compare, that you would get from passing the untransformed strings to compare in the derived class.


collate::do_hash

virtual long do_hash(const E *first, const E *last) const;

The protected virtual member function returns an integer derived from the values of the elements in the sequence [first, last). Such a hash value can be useful, for example, in distributing sequences pseudo-randomly across an array of lists.


collate::hash

long hash(const E *first, const E *last) const;

The member function returns do_hash (first, last).


collate::string_type

typedef basic_string<E> string_type;

The type describes a specialization of template class basic_string whose objects can store copies of the source sequence.


collate::transform

string_type transform(const E *first, const E *last) const;

The member function returns do_transform (first, last).


collate_byname

template<class E>
    class collate_byname : public collate<E> {
public:
    explicit collate_byname(const char *s, size_t refs = 0);
protected:
    ~collate_byname();
    };

The template class describes an object that can serve as a locale facet of type collate <E>. Its behavior is determined by the named locale s. The constructor initializes its base object with collate <E>(refs).


ctype

char_type · ctype · do_is · do_narrow · do_scan_is · do_scan_not · do_tolower · do_toupper · do_widen · is · narrow · scan_is · scan_not · tolower · toupper · widen

template<class E>
    class ctype : public locale::facet, public ctype_base {
public:
    typedef E char_type;
    explicit ctype(size_t refs = 0);
    bool is(mask msk, E ch) const;
    const E *is(const E *first, const E *last, mask *dst) const;
    const E *scan_is(mask msk, const E *first, const E *last) const;
    const E *scan_not(mask msk, const E *first, const E *last) const;
    E toupper(E ch) const;
    const E *toupper(E *first, E *last) const;
    E tolower(E ch) const;
    const E *tolower(E *first, E *last) const;
    E widen(char ch) const;
    const char *widen(char *first, char *last, E *dst) const;
    char narrow(E ch, char dflt) const;
    const E *narrow(const E *first, const E *last,
        char dflt, char *dst) const;
    static locale::id id;
protected:
    ~ctype();
    virtual bool do_is(mask msk, E ch) const;
    virtual const E *do_is(const E *first, const E *last,
        mask *dst) const;
    virtual const E *do_scan_is(mask msk, const E *first,
        const E *last) const;
    virtual const E *do_scan_not(mask msk, const E *first,
        const E *last) const;
    virtual E do_toupper(E ch) const;
    virtual const E *do_toupper(E *first, E *last) const;
    virtual E do_tolower(E ch) const;
    virtual const E *do_tolower(E *first, E *last) const;
    virtual E do_widen(char ch) const;
    virtual const char *do_widen(char *first, char *last, E *dst) const;
    virtual char do_narrow(E ch, char dflt) const;
    virtual const E *do_narrow(const E *first, const E *last,
        char dflt, char *dst) const;
    };

The template class describes an object that can serve as a locale facet, to characterize various properties of a "character" (element) of type E. Such a facet also converts between sequences of E elements and sequences of char.

An object of class ctype<E> stores a pointer to the first element of a ctype mask table, an array of UCHAR_MAX + 1 elements of type ctype_base:: mask. It also stores a Boolean object that indicates whether the array should be deleted when the ctype<E> object is destroyed.

As with any locale facet, the static object id has an initial stored value of zero. The first attempt to access its stored value stores a unique positive value in id.

The Standard C++ library defines two explicit specializations of this template class:

  • ctype<char>, whose differences are described separately
  • ctype<wchar_t<, which treats elements as wide characters

In this implementation, other specializations of template class ctype<E>:

  • Convert a value ch of type E to a value of type char with the expression (char)ch.
  • Convert a value c of type char to a value of type E with the expression E(c).

All other operations are performed on char values the same as for the specialization ctype<char>.


ctype::char_type

typedef E char_type;

The type is a synonym for the template parameter E.


ctype::ctype

explicit ctype(size_t refs = 0);

The type is a synonym for the template parameter E.


ctype::do_is

virtual bool do_is(mask msk, E ch) const;
virtual const E *do_is(const E *first, const E *last,
    mask *dst) const;

The first protected member template function returns true if table[(unsigned char)(char)ch] & msk is nonzero, where table is the stored pointer to the ctype mask table.

The second protected member template function stores in dst[I] the value table[(unsigned char)(char)first[I]] & msk, where I ranges over the interval [0, last - first).


ctype::do_narrow

virtual char do_narrow(E ch, char dflt) const;
virtual const E *do_narrow(const E *first, const E *last,
    char dflt, char *dst) const;

The first protected member template function returns (char)ch, or dflt if that expression is undefined.

The second protected member template function stores in dst[I] the value do_narrow(first[I], dflt), for I in the interval [0, last - first).


ctype::do_scan_is

virtual const E *do_scan_is(mask msk, const E *first,
    const E *last) const;

The protected member function returns the smallest pointer p in the range [first, last) for which do_is (msk, *p) is true. If no such value exists, the function returns last.


ctype::do_scan_not

virtual const E *do_scan_not(mask msk, const E *first,
    const E *last) const;

The protected member function returns the smallest pointer p in the range [first, last) for which do_is (msk, *p) is false. If no such value exists, the function returns last.


ctype::do_tolower

virtual E do_tolower(E ch) const;
virtual const E *do_tolower(E *first, E *last) const;

The first protected member template function returns the lowercase character corresponding to ch, if such a character exists. Otherwise, it returns ch.

The second protected member template function replaces each element first[I], for I in the interval [0, last - first), with do_tolower(first[I].


ctype::do_toupper

virtual E do_toupper(E ch) const;
virtual const E *do_toupper(E *first, E *last) const;

The first protected member template function returns the uppercase character corresponding to ch, if such a character exists. Otherwise, it returns ch.

The second protected member template function replaces each element first[I], for I in the interval [0, last - first), with do_toupper(first[I].


ctype::do_widen

virtual E do_widen(char ch) const;
virtual const char *do_widen(char *first, char *last, E *dst) const;

The first protected member template function returns E(ch).

The second protected member template function stores in dst[I] the value do_widen(first[I]), for I in the interval [0, last - first).


ctype::is

bool is(mask msk, E ch) const;
const E *is(const E *first, const E *last, mask *dst) const;

The first member function returns do_is (msk, ch). The second member function returns do_is(first, last, dst).


ctype::narrow

char narrow(E ch, char dflt) const;
const E *narrow(const E *first, const E *last,
    char dflt, char *dst) const;

The first member function returns do_narrow (ch, dflt). The second member function returns do_narrow(first, last, dflt, dst).


ctype::scan_is

const E *scan_is(mask msk, const E *first, const E *last) const;

The member function returns do_scan_is (msk, first, last).


ctype::scan_not

const E *scan_not(mask msk, const E *first, const E *last) const;

The member function returns do_scan_not (msk, first, last).


ctype::tolower

E tolower(E ch) const;
const E *tolower(E *first, E *last) const;

The member function returns do_tolower (first, last).


ctype::toupper

E toupper(E ch) const;
const E *toupper(E *first, E *last) const;

The member function returns do_toupper (first, last).


ctype::widen

E widen(char ch) const;
const char *widen(char *first, char *last, E *dst) const;

The member function returns do_widen (first, last, dst).


ctype<char>

class ctype<char> : public locale::facet, public ctype_base {
public:
    typedef char char_type;
    explicit ctype(const mask *tab = 0, bool del = false,
        size_t refs = 0);
    bool is(mask msk, char ch) const;
    const char *is(const char *first, const char *last,
        mask *dst) const;
    const char *scan_is(mask msk,
        const char *first, const char *last) const;
    const char *scan_not(mask msk,
        const char *first, const char *last) const;
    char toupper(char ch) const;
    const char *toupper(char *first, char *last) const;
    char tolower(char ch) const;
    const char *tolower(char *first, char *last) const;
    char widen(char ch) const;
    const char *widen(char *first, char *last, char *dst) const;
    char narrow(char ch, char dflt) const;
    const char *narrow(const char *first, const char *last,
        char dflt, char *dst) const;
    static locale::id id;
protected:
    ~ctype();
    virtual char do_toupper(char ch) const;
    virtual const char *do_toupper(char *first, char *last) const;
    virtual char do_tolower(char ch) const;
    virtual const char *do_tolower(char *first, char *last) const;
    const mask *table() const throw();
    static const mask *classic_table() const throw();
    static const size_t table_size;
    };

The class is an explicit specialization of template class ctype for type char. Hence, it describes an object that can serve as a locale facet, to characterize various properties of a "character" (element) of type char. The explicit specialization differs from the template class in several ways:

  • Its sole public constructor lets you specify tab, the ctype mask table, and del, the Boolean object that is true if the array should be deleted when the ctype<char> object is destroyed -- as well as the usual reference-count parameter refs.
  • The protected member function table() returns the stored ctype mask table.
  • The static member object table_size specifies the minimum number of elements in a ctype mask table.
  • The protected static member function classic_table() returns the ctype mask table appropriate to the "C" locale.
  • There are no protected virtual member functions do_is, do_narrow, do_scan_is, do_scan_not, or do_widen. The corresponding public member functions perform the equivalent operations themselves.
  • The member functions narrow and widen simply copy elements unaltered.


ctype_base

class ctype_base {
public:
    enum mask;
    static const mask space, print, cntrl,
        upper, lower, digit, punct, xdigit,
        alpha, alnum, graph;
    };

The class serves as a base class for facets of template class ctype. It defines just the enumerated type mask and several constants of this type. Each of the constants characterizes a different way to classify characters, as defined by the functions with similar names declared in the header <ctype.h>. The constants are:

  • space (function isspace)
  • print (function isprint)
  • cntrl (function iscntrl)
  • upper (function isupper)
  • lower (function islower)
  • digit (function isdigit)
  • punct (function ispunct)
  • xdigit (function isxdigit)
  • alpha (function isalpha)
  • alnum (function isalnum)
  • graph (function isgraph)

You can characterize a combination of classifications by ORing these constants. In particular, it is always true that alnum == (alpha | digit) and graph == (alnum | punct).


ctype_byname

template<class E>
    class ctype_byname : public ctype<E> {
public:
    explicit ctype_byname(const char *s, size_t refs = 0);
protected:
    ~ctype_byname();
    };

The template class describes an object that can serve as a locale facet of type ctype <E>. Its behavior is determined by the named locale s. The constructor initializes its base object with ctype <E>(refs) (or the equivalent for base class ctype<char>).


has_facet

template<class Facet>
    bool has_facet(const locale& loc, const Facet *fac);

The template function returns true if a locale facet of class Facet is listed within the locale object loc.

In this implementation, you should write _HAS(loc, Facet) in place of has_facet(loc, (Facet *)0), because the second parameter is a nonstandard extension.


isalnum

template<class E>
    bool isalnum(E c, const locale& loc) const;

The template function returns use_facet < ctype <E> >(loc). is (ctype<E>:: alnum , c).


isalpha

template<class E>
    bool isalpha(E c, const locale& loc) const;

The template function returns use_facet < ctype <E> >(loc). is (ctype<E>:: alpha , c).


iscntrl

template<class E>
    bool iscntrl(E c, const locale& loc) const;

The template function returns use_facet < ctype <E> >(loc). is (ctype<E>:: cntrl , c).


isdigit

template<class E>
    bool isdigit(E c, const locale& loc) const;

The template function returns use_facet < ctype <E> >(loc). is (ctype<E>:: digit , c).


isgraph

template<class E>
    bool isgraph(E c, const locale& loc) const;

The template function returns use_facet < ctype <E> >(loc). is (ctype<E>:: graph , c).


islower

template<class E>
    bool islower(E c, const locale& loc) const;

The template function returns use_facet < ctype <E> >(loc). is (ctype<E>:: lower , c).


isprint

template<class E>
    bool isprint(E c, const locale& loc) const;

The template function returns use_facet < ctype <E> >(loc). is (ctype<E>:: print , c).


ispunct

template<class E>
    bool ispunct(E c, const locale& loc) const;

The template function returns use_facet < ctype <E> >(loc). is (ctype<E>:: punct , c).


isspace

template<class E>
    bool isspace(E c, const locale& loc) const;

The template function returns use_facet < ctype <E> >(loc). is (ctype<E>:: space , c).


isupper

template<class E>
    bool isupper(E c, const locale& loc) const;

The template function returns use_facet < ctype <E> >(loc). is (ctype<E>:: upper , c).


isxdigit

template<class E>
    bool isxdigit(E c, const locale& loc) const;

The template function returns use_facet < ctype <E> >(loc). is (ctype<E>:: xdigit , c).


locale

category · classic · facet · global · id · locale · name · operator!= · operator() · operator==

class locale {
public:
    class facet;
    class id;
    typedef int category;
    static const category none, collate, ctype, monetary,
        numeric, time, messages, all;
    locale();
    explicit locale(const char *s);
    locale(const locale& x, const locale& y,
        category cat);
    locale(const locale& x, const char *s, category cat);
    bool operator()(const string& lhs,
        const string& rhs) const;
    string name() const;
    bool operator==(const locale& x) const;
    bool operator!=(const locale& x) const;
    static locale global(const locale& x);
    static const locale& classic();
    };

The class describes a locale object that encapsulates a locale. It represents culture-specific information as a list of facets. A facet is a pointer to an object of a class derived from class facet that has a public object of the form:

static locale::id id;

You can define an open-ended set of these facets. You can also construct a locale object that designates an arbitrary number of facets.

Predefined groups of these facets represent the locale categories traditionally managed in the Standard C library by the function setlocale.

Category collate (LC_COLLATE) includes the facets:

collate<char>
collate<wchar_t>

Category ctype (LC_CTYPE) includes the facets:

ctype<char>
ctype<wchar_t>
codecvt<char, char, mbstate_t>
codecvt<wchar_t, char, mbstate_t>

Category monetary (LC_MONETARY) includes the facets:

moneypunct<char, false>
moneypunct<wchar_t, false>
moneypunct<char, true>
moneypunct<wchar_t, true>
money_get<char, istreambuf_iterator<char> >
money_get<wchar_t, istreambuf_iterator<wchar_t> >
money_put<char, ostreambuf_iterator<char> >
money_put<wchar_t, ostreambuf_iterator<wchar_t> >

Category numeric (LC_NUMERIC) includes the facets:

num_get<char, istreambuf_iterator<char> >
num_get<wchar_t, istreambuf_iterator<wchar_t> >
num_put<char, ostreambuf_iterator<char> >
num_put<wchar_t, ostreambuf_iterator<wchar_t> >
numpunct<char>
numpunct<wchar_t>

Category time (LC_TIME) includes the facets:

time_get<char, istreambuf_iterator<char> >
time_get<wchar_t, istreambuf_iterator<wchar_t> >
time_put<char, ostreambuf_iterator<char> >
time_put<wchar_t, ostreambuf_iterator<wchar_t> >

Category messages (LC_MESSAGE) includes the facets:

messages<char>
messages<wchar_t>

(The last category is required by Posix, but not the C Standard.)

Some of these predefined facets are used by the iostreams classes to control the conversion of numeric values to and from text sequences.

An object of class locale also stores a locale name as an object of class string. Using an invalid locale name to construct a locale facet or a locale object throws an object of class runtime_error. If the stored locale name is "*", no C-style locale corresponds exactly to that represented by the object. Otherwise, you can establish a matching locale within the Standard C library by calling setlocale( LC_ALL, x. name . c_str ()).

In this implementation, you can also call the static member function:

static locale empty();

to construct a locale object that has no facets. It is also a transparent locale -- the template function use_facet consults the global locale if it cannot find the requested facet in a transparent locale. Thus, you can write:

cout.imbue(locale::empty());

Subsequent insertions to cout are mediated by the current state of the global locale. You can even write:

locale loc(locale::empty(), locale("C"), locale::numeric);
cout.imbue(loc);

Numeric formatting rules remain the same as in the C locale even as the global locale supplies changing rules for inserting dates and monetary amounts.


locale::category

typedef int category;
static const category none, collate, ctype, monetary,
    numeric, time, messages, all;

The type is a synonym for int, so that it can represent any of the C locale categories. It can also represent a group of constants local to class locale:

  • none, corresponding to none of the C categories
  • collate, corresponding to the C category LC_COLLATE
  • ctype, corresponding to the C category LC_CTYPE
  • monetary, corresponding to the C category LC_MONETARY
  • numeric, corresponding to the C category LC_NUMERIC
  • time, corresponding to the C category LC_TIME
  • messages, corresponding to the Posix category LC_MESSAGE
  • all, corresponding to the C union of all categories LC_ALL

You can represent an arbitrary group of categories by ORing these constants, as in monetary | time.


locale::classic

static const locale& classic();

The static member function returns a locale object that represents the C locale.


locale::facet

class facet {
protected:
    explicit facet(size_t refs = 0);
    virtual ~facet();
private:
    facet(const facet&)          // not defined
    void operator=(const facet&) // not defined
    };

The member class serves as the base class for all locale facets. Note that you can neither copy nor assign an object of class facet. You can construct and destroy objects derived from class locale::facet, but not objects of the base class proper. Typically, you construct an object myfac derived from facet when you construct a locale, as in:

locale loc(locale::classic(), new myfac);

In such cases, the constructor for the base class facet should have a zero refs argument. When the object is no longer needed, it is deleted. Thus, you supply a nonzero refs argument only in those rare cases where you take responsibility for the lifetime of the object.


locale::global

static locale global(const locale& x);

The static member function stores a copy of x as the global locale. It also calls setlocale( LC_ALL, x. name . c_str ()), to establish a matching locale within the Standard C library. The function then returns the previous global locale. At program startup, the global locale represents the C locale.


locale::id

class id {
protected:
    id();
private:
    id(const id&)             // not defined
    void operator=(const id&) // not defined
    };

The member class describes the static member object required by each unique locale facet. Note that you can neither copy nor assign an object of class id.


locale::locale

locale();
explicit locale(const char *s);
locale(const locale& x, const locale& y,
    category cat);
locale(const locale& x, const char *s, category cat);

The first constructor initializes the object to match the global locale. The second constructor initializes all the locale categories to have behavior consistent with the locale name s. The remaining constructors copy x, with the exceptions noted:

locale(const locale& x, const locale& y,
    category cat);

replaces from y those facets corresponding to a category c for which c & cat is nonzero.

locale(const locale& x, const char *s, category cat);

replaces from locale(s, all) those facets corresponding to a category c for which c & cat is nonzero.

In this implementation, you should write _ADDFAC(loc, Facet) to return a new locale that adds the facet Facet to the locale loc, since not all translators currently support the additional template constructors:

template<class Facet>
    locale(const locale& x, Facet *fac);
template<class Facet>
    locale(const locale& x, const locale& y);

If a locale name s is a null pointer or otherwise invalid, the function throws runtime_error.


locale::name

string name() const;

The member function returns the stored locale name.


locale::operator!=

bool operator!=(const locale& x) const;

The member function returns !(*this == x).


locale::operator()

bool operator()(const string& lhs, const string& rhs);

The member function effectively executes:

const collate<E>& fac = use_fac<collate<E> >(*this);
return (fac.compare(lhs.begin(), lhs.end(),
    rhs.begin(), rhs.end()) < 0);

Thus, you can use a locale object as a function object.

In this implementation, if a translator does not support member template functions, the template:

template<class E, class T, class A>
    bool operator()(const basic_string<E, T, A>& lhs,
        const basic_string<E, T, A>& rhs);

is replaced by:

bool operator()(const string& lhs, const string& rhs);


locale::operator==

bool operator==(const locale& x) const;

The member function returns true only if *this and x are copies of the same locale or have the same name (other than "*").


messages

template<class E>
    class messages : public locale::facet, public messages_base {
public:
    typedef E char_type;
    typedef basic_string<E> string_type;
    explicit messages(size_t refs = 0);
    catalog open(const string& name,
        const locale& loc) const;
    string_type get(catalog cat, int set, int msg,
        const string_type& dflt) const;
    void close(catalog cat) const;
    static locale::id id;
protected:
    ~messages();
    virtual catalog do_open(const string& name,
        const locale& loc) const;
    virtual string_type do_get(catalog cat, int set, int msg,
        const string_type& dflt) const;
    virtual void do_close(catalog cat) const;
    };

The template class describes an object that can serve as a locale facet, to characterize various properties of a message catalog that can supply messages represented as sequences of elements of type E.

As with any locale facet, the static object id has an initial stored value of zero. The first attempt to access its stored value stores a unique positive value in id.


messages::char_type

typedef E char_type;

The type is a synonym for the template parameter E.


messages::close

void close(catalog cat) const;

The member function calls do_close (cat);.


messages::do_close

virtual void do_close(catalog cat) const;

The protected member function closes the message catalog, which must have been opened by an earlier call to do_open.


messages::do_get

virtual string_type do_get(catalog cat, int set, int msg,
    const string_type& dflt) const;

The protected member function endeavors to obtain a message sequence from the message catalog cat. It may make use of set, msg, and dflt in doing so. It returns a copy of dflt on failure. Otherwise, it returns a copy of the specified message sequence.

In this implementation, the function returns a locale-specific version of the sequence no if msg is zero. It returns a locale-specific version of the sequence yes if msg is one. Otherwise, it returns dflt.


messages::do_open

virtual catalog do_open(const string& name,
    const locale& loc) const;

The protected member function endeavors to open a message catalog whose name is name. It may make use of the locale loc in doing so. It returns a value that compares less than zero on failure. Otherwise, the returned value can be used as the first argument on a later call to get. It should in any case be used as the argument on a later call to close.

In this implementation, the function always returns zero.


messages::get

string_type get(catalog cat, int set, int msg,
     const string_type& dflt) const;

The member function returns do_get (cat, set, msg, dflt);.


messages::messages

explicit messages(size_t refs = 0);

The constructor initializes its base object with locale:: facet (refs).


messages::open

catalog open(const string& name,
    const locale& loc) const;

The member function returns do_open (name, loc);.


messages::string_type

typedef basic_string<E> string_type;

The type describes a specialization of template class basic_string whose objects can store copies of the message sequences.


messages_base

class messages_base {
    typedef int catalog;
    };

The class describes a type common to all specializations of template class messages. The type catalog is a synonym for type int that describes the possible return values from messages:: do_open.


messages_byname

template<class E>
    class messages_byname : public messages<E> {
public:
    explicit messages_byname(const char *s, size_t refs = 0);
protected:
    ~messages_byname();
    };

The template class describes an object that can serve as a locale facet of type messages <E>. Its behavior is determined by the named locale s. The constructor initializes its base object with messages <E>(refs).


money_base

class money_base {
    enum part {none, sign, space,
        symbol, value};
    struct pattern {
        char field[4];
        };
    };

The class describes an enumeration and a structure common to all specializations of template class moneypunct. The enumeration part describes the possible values in elements of the array field in the structure pattern. The values of part are:

  • none to match zero or more spaces or generate nothing
  • sign to match or generate a positive or negative sign
  • space to match zero or more spaces or generate a space
  • symbol to match or generate a currency symbol
  • value to match or generate a monetary value


money_get

template<class E,
    class InIt = istreambuf_iterator<E> >
    class money_get : public locale::facet {
public:
    typedef E char_type;
    typedef InIt iter_type;
    typedef basic_string<E> string_type;
    explicit money_get(size_t refs = 0);
    iter_type get(iter_type first, iter_type last, bool intl,
        ios_base& x, ios_base::iostate& st, long double& val) const;
    iter_type get(iter_type first, iter_type last, bool intl,
        ios_base& x, ios_base::iostate& st, string_type& val) const;
    static locale::id id;
protected:
    ~money_get();
    virtual iter_type do_get(iter_type first, iter_type last, bool intl,
        ios_base& x, ios_base::iostate& st, string_type& val) const;
    virtual iter_type do_get(iter_type first, iter_type last, bool intl,
        ios_base& x, ios_base::iostate& st, long double& val) const;
    };

The template class describes an object that can serve as a locale facet, to control conversions of sequences of type E to monetary values.

As with any locale facet, the static object id has an initial stored value of zero. The first attempt to access its stored value stores a unique positive value in id.


money_get::char_type

typedef E char_type;

The type is a synonym for the template parameter E.


money_get::do_get

virtual iter_type do_get(iter_type first, iter_type last, bool intl,
    ios_base& x, ios_base::iostate& st, string_type& val) const;
virtual iter_type do_get(iter_type first, iter_type last, bool intl,
    ios_base& x, ios_base::iostate& st, long double& val) const;

The first virtual protected member function endeavors to match sequential elements beginning at first in the sequence [first, last) until it has recognized a complete, nonempty monetary input field. If successful, it converts this field to a sequence of one or more decimal digits, optionally preceded by a minus sign (-), to represent the amount and stores the result in the string_type object val. It returns an iterator designating the first element beyond the monetary input field. Otherwise, the function stores an empty sequence in val and sets ios_base::failbit in st. It returns an iterator designating the first element beyond any prefix of a valid monetary input field. In either case, if the return value equals last, the function sets ios_base::eofbit in st.

The second virtual protected member function behaves the same as the first, except that, if successful, it converts the optionally-signed digit sequence to a value of type long double and stores that value in val.

The format of a monetary input field is determined by the locale facet fac returned by the (effective) call use_facet < moneypunct <E, intl>(x. getloc ()). Specifically:

  • fac. neg_format () determines the order in which components of the field occur
  • fac. curr_symbol () determines the sequence of elements that constitutes a currency symbol
  • fac. positive_sign () determines the sequence of elements that constitutes a positive sign
  • fac. negative_sign () determines the sequence of elements that constitutes a negative sign
  • fac. grouping () determines how digits are grouped to the left of any decimal point
  • fac. thousands_sep () determines the element that separates groups of digits to the left of any decimal point
  • fac. decimal_point () determines the element that separates the integer digits from the fraction digits
  • fac. frac_digits () determines the number of significant fraction digits to the right of any decimal point

If the sign string (fac.negative_sign or fac.positive_sign) has more than one element, only the first element is matched where the element equal to money_base:: sign appears in the format pattern (fac.neg_format). Any remaining elements are matched at the end of the monetary input field. If neither string has a first element that matches the next element in the monetary input field, the sign string is taken as empty and the sign is positive.

If x. flags () & showbase is nonzero, the string fac.curr_symbol must match where the element equal to money_base:: symbol appears in the format pattern. Otherwise, if money_base::symbol occurs at the end of the format pattern, and if no elements of the sign string remain to be matched, the currency symbol is not matched. Otherwise, the currency symbol is optionally matched.

If no instances of fac.thousands_sep() occur in the value portion of the monetary input field (where the element equal to money_base:: value appears in the format pattern), no grouping constraint is imposed. Otherwise, any grouping constraints imposed by fac.grouping() are enforced. Note that the resulting digit sequence represents an integer whose low-order fac.frac_digits() decimal digits are considered to the right of the decimal point.

Arbitrary white space is matched where the element equal to money_base:: space appears in the format pattern, if it appears other than at the end of the format pattern. Otherwise, no internal white space is matched. An element c is considered white space if use_facet < ctype <E>(x. getloc ()). is (ctype_base:: space , c) is true.


money_get::get

iter_type get(iter_type first, iter_type last, bool intl,
    ios_base& x, ios_base::iostate& st, long double& val) const;
iter_type get(iter_type first, iter_type last, bool intl,
    ios_base& x, ios_base::iostate& st, string_type& val) const;

Both member functions return do_get (first, last, intl, x, st, val).


money_get::iter_type

typedef InIt iter_type;

The type is a synonym for the template parameter InIt.


money_get::money_get

explicit money_get(size_t refs = 0);

The constructor initializes its base object with locale:: facet (refs).


money_get::string_type

typedef basic_string<E> string_type;

The type describes a specialization of template class basic_string whose objects can store sequences of elements from the source sequence.


money_put

template<class E,
    class OutIt = ostreambuf_iterator<E> >
    class money_put : public locale::facet {
public:
    typedef E char_type;
    typedef OutIt iter_type;
    typedef basic_string<E> string_type;
    explicit money_put(size_t refs = 0);
    iter_type put(iter_type next, bool intl, ios_base& x,
        E fill, long double& val) const;
    iter_type put(iter_type next, bool intl, ios_base& x,
        E fill, string_type& val) const;
    static locale::id id;
protected:
    ~money_put();
    virtual iter_type do_put(iter_type next, bool intl,
        ios_base& x, E fill, string_type& val) const;
    virtual iter_type do_put(iter_type next, bool intl,
        ios_base& x, E fill, long double& val) const;
    };

The template class describes an object that can serve as a locale facet, to control conversions of monetary values to sequences of type E.

As with any locale facet, the static object id has an initial stored value of zero. The first attempt to access its stored value stores a unique positive value in id.


money_put::char_type

typedef E char_type;

The type is a synonym for the template parameter E.


money_put::do_put

virtual iter_type do_put(iter_type next, bool intl,
    ios_base& x, E fill, string_type& val) const;
virtual iter_type do_put(iter_type next, bool intl,
    ios_base& x, E fill, long double& val) const;

The first virtual protected member function generates sequential elements beginning at next to produce a monetary output field from the string_type object val. The sequence controlled by val must begin with one or more decimal digits, optionally preceded by a minus sign (-), which represents the amount. The function returns an iterator designating the first element beyond the generated monetary output field.

The second virtual protected member function behaves the same as the first, except that it effectively first converts val to a sequence of decimal digits, optionally preceded by a minus sign, then converts that sequence as above.

The format of a monetary output field is determined by the locale facet fac returned by the (effective) call use_facet < moneypunct <E, intl>(x. getloc ()). Specifically:

  • fac. pos_format () determines the order in which components of the field are generated for a non-negative value.
  • fac. neg_format () determines the order in which components of the field are generated for a negative value.
  • fac. curr_symbol () determines the sequence of elements to generate for a currency symbol.
  • fac. positive_sign () determines the sequence of elements to generate for a positive sign.
  • fac. negative_sign () determines the sequence of elements to generate for a negative sign.
  • fac. grouping () determines how digits are grouped to the left of any decimal point.
  • fac. thousands_sep () determines the element that separates groups of digits to the left of any decimal point.
  • fac. decimal_point () determines the element that separates the integer digits from any fraction digits.
  • fac. frac_digits () determines the number of significant fraction digits to the right of any decimal point.

If the sign string (fac.negative_sign or fac.positive_sign) has more than one element, only the first element is generated where the element equal to money_base:: sign appears in the format pattern (fac.neg_format or fac.pos_format). Any remaining elements are generated at the end of the monetary output field.

If x. flags () & showbase is nonzero, the string fac.curr_symbol is generated where the element equal to money_base:: symbol appears in the format pattern. Otherwise, no currency symbol is generated.

If no grouping constraints are imposed by fac.grouping() (its first element has the value CHAR_MAX), then no instances of fac.thousands_sep() are generated in the value portion of the monetary output field (where the element equal to money_base:: value appears in the format pattern). If fac.frac_digits() is zero, then no instance of fac.decimal_point() is generated after the decimal digits. Otherwise, the resulting monetary output field places the low-order fac.frac_digits() decimal digits to the right of the decimal point.

Padding occurs as for any numeric output field, except that if x.flags() & x. internal is nonzero, any internal padding is generated where the element equal to money_base:: space appears in the format pattern, if the element does appear. Otherwise, internal padding occurs before the generated sequence. The padding character is fill.

The function calls x.width(0) to reset the field width to zero.


money_put::put

iter_type put(iter_type next, bool intl, ios_base& x,
    E fill, long double& val) const;
iter_type put(iter_type iter_type next, bool intl, ios_base& x,
    E fill, string_type& val) const;

Both member functions return do_put (next, intl, x, fill, val).


money_put::iter_type

typedef InIt iter_type;

The type is a synonym for the template parameter OutIt.


money_put::money_put

explicit money_put(size_t refs = 0);

The constructor initializes its base object with locale:: facet (refs).


money_put::string_type

typedef basic_string<E> string_type;

The type describes a specialization of template class basic_string whose objects can store sequences of elements from the source sequence.


moneypunct

char_type · curr_symbol · decimal_point · do_curr_symbol · do_decimal_point · do_frac_digits · do_grouping · do_neg_format · do_negative_sign · do_pos_format · do_positive_sign · do_thousands_sep · frac_digits · grouping · moneypunct · neg_format · negative_sign · pos_format · positive_sign · string_type · thousands_sep

template<class E, bool Intl>
    class moneypunct : public locale::facet, public money_base {
public:
    typedef E char_type;
    typedef basic_string<E> string_type;
    explicit moneypunct(size_t refs = 0);
    E decimal_point() const;
    E thousands_sep() const;
    string grouping() const;
    string_type curr_symbol() const;
    string_type positive_sign() const;
    string_type negative_sign() const;
    int frac_digits() const;
    pattern pos_format(  oonst;
    pattern neg_format() const;
    static const bool intl = Intl;
    static locale::id id;
protected:
    ~moneypunct();
    virtual E do_decimal_point() const;
    virtual E do_thousands_sep() const;
    virtual string do_grouping() const;
    virtual string_type do_curr_symbol() const;
    virtual string_type do_positive_sign() const;
    virtual string_type do_negative_sign() const;
    virtual int do_frac_digits() const;
    virtual pattern do_pos_format() const;
    virtual pattern do_neg_format() const;
    };

The template class describes an object that can serve as a locale facet, to describe the sequences of type E used to represent a monetary input field or a monetary output field. If the template parameter Intl is true, international conventions are observed.

As with any locale facet, the static object id has an initial stored value of zero. The first attempt to access its stored value stores a unique positive value in id.

The const static object intl stores the value of the template parameter Intl.


moneypunct::char_type

typedef E char_type;

The type is a synonym for the template parameter E.


moneypunct::curr_symbol

string_type curr_symbol() const;

The member function returns do_curr_symbol ().


moneypunct::decimal_point

E decimal_point() const;

The member function returns do_decimal_point ().


moneypunct::do_curr_symbol

string_type do_curr_symbol() const;

The protected virtual member function returns a locale-specific sequence of elements to use as a currency symbol.


moneypunct::do_decimal_point

E do_decimal_point() const;

The protected virtual member function returns a locale-specific element to use as a decimal point.


moneypunct::do_frac_digits

int do_frac_digits() const;

The protected virtual member function returns a locale-specific count of the number of digits to display to the right of any decimal point.


moneypunct::do_grouping

string do_grouping() const;

The protected virtual member function returns a locale-specific rule for determining how digits are grouped to the left of any decimal point. The encoding is the same as for lconv::grouping.


moneypunct::do_neg_format

pattern do_neg_format() const;

The protected virtual member function returns a locale-specific rule for determining how to generate a monetary output field for a negative amount. Each of the four elements of pattern:: field can have the values:

  • none to match zero or more spaces or generate nothing
  • sign to match or generate a positive or negative sign
  • space to match zero or more spaces or generate a space
  • symbol to match or generate a currency symbol
  • value to match or generate a monetary value

Components of a monetary output field are generated (and components of a monetary input field are matched) in the order in which these elements appear in pattern::field. Each of the values sign, symbol, value, and either none or space must appear exactly once. The value none must not appear first. The value space must not appear first or last. If Intl is true, the order is symbol, sign, none, then value.

The template version of moneypunct<E, Intl> returns {money_base::symbol, money_base::sign, money_base::value, money_base::none}.


moneypunct::do_negative_sign

string_type do_negative_sign() const;

The protected virtual member function returns a locale-specific sequence of elements to use as a negative sign.


moneypunct::do_pos_format

pattern do_pos_format() const;

The protected virtual member function returns a locale-specific rule for determining how to generate a monetary output field for a positive amount. (It also determines how to match the components of a monetary input field.) The encoding is the same as for do_neg_format.

The template version of moneypunct<E, Intl> returns {money_base::symbol, money_base::sign, money_base::value, money_base::none}.


moneypunct::do_positive_sign

string_type do_positive_sign() const;

The protected virtual member function returns a locale-specific sequence of elements to use as a positive sign.


moneypunct::do_thousands_sep

E do_thousands_sep() const;

The protected virtual member function returns a locale-specific element to use as a group separator to the left of any decimal point.


moneypunct::frac_digits

int frac_digits() const;

The member function returns do_frac_digits ().


moneypunct::grouping

string grouping() const;

The member function returns do_grouping ().


moneypunct::moneypunct

explicit moneypunct(size_t refs = 0);

The constructor initializes its base object with locale:: facet (refs).


moneypunct::neg_format

pattern neg_format() const;

The member function returns do_neg_format ().


moneypunct::negative_sign

string_type negative_sign() const;

The member function returns do_negative_sign ().


moneypunct::pos_format

pattern pos_format() const;

The member function returns do_pos_format ().


moneypunct::positive_sign

string_type positive_sign() const;

The member function returns do_positive_sign ().


moneypunct::string_type

typedef basic_string<E> string_type;

The type describes a specialization of template class basic_string whose objects can store copies of the punctuation sequences.


moneypunct::thousands_sep

E thousands_sep() const;

The member function returns do_thousands_sep ().


moneypunct_byname

template<class E, bool Intl>
    class moneypunct_byname : public moneypunct<E, Intl> {
public:
    explicit moneypunct_byname(const char *s, size_t refs = 0);
protected:
    ~moneypunct_byname();
    };

The template class describes an object that can serve as a locale facet of type moneypunct <E, Intl>. Its behavior is determined by the named locale s. The constructor initializes its base object with moneypunct <E, Intl>(refs).


num_get

template<class E, class InIt = istreambuf_iterator<E> >
    class num_get : public locale::facet {
public:
    typedef E char_type;
    typedef InIt iter_type;
    explicit num_get(size_t refs = 0);
    iter_type get(iter_type first, iter_type last, ios_base& x,
        ios_base::iostate& st, long& val) const;
    iter_type get(iter_type first, iter_type last, ios_base& x,
        ios_base::iostate& st, unsigned long& val) const;
    iter_type get(iter_type first, iter_type last, ios_base& x,
        ios_base::iostate& st, double& val) const;
    iter_type get(iter_type first, iter_type last, ios_base& x,
        ios_base::iostate& st, long double& val) const;
    iter_type get(iter_type first, iter_type last, ios_base& x,
        ios_base::iostate& st, void *& val) const;
    iter_type get(iter_type first, iter_type last, ios_base& x,
        ios_base::iostate& st, bool& val) const;

    static locale::id id;
protected:
    ~num_get();
    virtual iter_type do_get(iter_type first, iter_type last,
        ios_base& x, ios_base::iostate& st, long& val) const;
    virtual iter_type do_get(iter_type first, iter_type last,
        ios_base& x, ios_base::iostate& st, unsigned long& val) const;
    virtual iter_type do_get(iter_type first, iter_type last,
        ios_base& x, ios_base::iostate& st, double& val) const;
    virtual iter_type do_get(iter_type first, iter_type last,
        ios_base& x, ios_base::iostate& st, long double& val) const;
    virtual iter_type do_get(iter_type first, iter_type last,
        ios_base& x, ios_base::iostate& st, void *& val) const;
    virtual iter_type do_get(iter_type first, iter_type last,
        ios_base& x, ios_base::iostate& st, bool& val) const;
    };

The template class describes an object that can serve as a locale facet, to control conversions of sequences of type E to numeric values.

As with any locale facet, the static object id has an initial stored value of zero. The first attempt to access its stored value stores a unique positive value in id.


num_get::char_type

typedef E char_type;

The type is a synonym for the template parameter E.


num_get::do_get

virtual iter_type do_get(iter_type first, iter_type last,
    ios_base& x, ios_base::iostate& st, long& val) const;
virtual iter_type do_get(iter_type first, iter_type last,
    ios_base& x, ios_base::iostate& st, unsigned long& val) const;
virtual iter_type do_get(iter_type first, iter_type last,
    ios_base& x, ios_base::iostate& st, double& val) const;
virtual iter_type do_get(iter_type first, iter_type last,
    ios_base& x, ios_base::iostate& st, long double& val) const;
virtual iter_type do_get(iter_type first, iter_type last,
    ios_base& x, ios_base::iostate& st, void *& val) const;
virtual iter_type do_get(iter_type first, iter_type last,
    ios_base& x, ios_base::iostate& st, bool& val) const;

The first virtual protected member function endeavors to match sequential elements beginning at first in the sequence [first, last) until it has recognized a complete, nonempty integer input field. If successful, it converts this field to its equivalent value as type long, and stores the result in val. It returns an iterator designating the first element beyond the numeric input field. Otherwise, the function stores nothing in val and sets ios_base::failbit in st. It returns an iterator designating the first element beyond any prefix of a valid integer input field. In either case, if the return value equals last, the function sets ios_base::eofbit in st.

The integer input field is converted by the same rules used by the scan functions for matching and converting a series of char elements from a file. (Each such char element is assumed to map to an equivalent element of type E by a simple, one-to-one, mapping.) The equivalent scan conversion specification is determined as follows:

  • If x. flags () & ios_base:: basefield == ios_base:: oct, the conversion specification is lo.
  • If x.flags() & ios_base::basefield == ios_base:: hex, the conversion specification is lx.
  • If x.flags() & ios_base::basefield == 0, the conversion specification is li.
  • Otherwise, the conversion specification is ld.

The format of an integer input field is further determined by the locale facet fac returned by the call use_facet < numpunct <E>(x. getloc ()). Specifically:

  • fac. grouping () determines how digits are grouped to the left of any decimal point.
  • fac. thousands_sep () determines the sequence that separates groups of digits to the left of any decimal point.

If no instances of fac.thousands_sep() occur in the numeric input field, no grouping constraint is imposed. Otherwise, any grouping constraints imposed by fac.grouping() is enforced and separators are removed before the scan conversion occurs.

The second virtual protected member function:

virtual iter_type do_get(iter_type first, iter_type last,
    ios_base& x, ios_base::iostate& st, unsigned long& val) const;

behaves the same as the first, except that it replaces a conversion specification of ld with lu. If successful it converts the numeric input field to a value of type unsigned long and stores that value in val.

The third virtual protected member function:

virtual iter_type do_get(iter_type first, iter_type last,
    ios_base& x, ios_base::iostate& st, double& val) const;

behaves the same as the first, except that it endeavors to match a complete, nonempty floating-point input field. fac. decimal_point () determines the sequence that separates the integer digits from the fraction digits. The equivalent scan conversion specifier is lf.

The fourth virtual protected member function:

virtual iter_type do_get(iter_type first, iter_type last,
    ios_base& x, ios_base::iostate& st, long double& val) const;

behaves the same as the third, except that the equivalent scan conversion specifier is Lf.

The fifth virtual protected member function:

virtual iter_type do_get(iter_type first, iter_type last,
    ios_base& x, ios_base::iostate& st, void *& val) const;

behaves the same as the first, except that the equivalent scan conversion specifier is p.

The sixth virtual protected member function:

virtual iter_type do_get(iter_type first, iter_type last, ios_base& x,
    ios_base::iostate& st, bool& val) const;

behaves the same as the first, except that it endeavors to match a complete, nonempty Boolean input field. If successful, it converts the Boolean input field to a value of type bool and stores that value in val.

A Boolean input field takes one of two forms. If x.flags() & ios_base:: boolalpha is false, it is the same as an integer input field, except that the converted value must be either 0 (for false) or 1 (for true). Otherwise, the sequence must match either fac. falsename () (for false), or fac. truename () (for true).


num_get::get

iter_type get(iter_type first, iter_type last, ios_base& x,
    ios_base::iostate& st, long& val) const;
iter_type get(iter_type first, iter_type last, ios_base& x,
    ios_base::iostate& st, unsigned long& val) const;
iter_type get(iter_type first, iter_type last, ios_base& x,
    ios_base::iostate& st, double& val) const;
iter_type get(iter_type first, iter_type last, ios_base& x,
    ios_base::iostate& st, long double& val) const;
iter_type get(iter_type first, iter_type last, ios_base& x,
    ios_base::iostate& st, void *& val) const;
iter_type get(iter_type first, iter_type last, ios_base& x,
    ios_base::iostate& st, bool& val) const;

All member functions return do_get (first, last, x, st, val).


num_get::iter_type

typedef InIt iter_type;

The type is a synonym for the template parameter InIt.


num_get::num_get

explicit num_get(size_t refs = 0);

The constructor initializes its base object with locale:: facet (refs).


num_put

template<class E, class OutIt = ostreambuf_iterator<E> >
    class num_put : public locale::facet {
public:
    typedef E char_type;
    typedef OutIt iter_type;
    explicit num_put(size_t refs = 0);
    iter_type put(iter_type next, ios_base& x,
        E fill, long val) const;
    iter_type put(iter_type next, ios_base& x,
        E fill, unsigned long val) const;
    iter_type put(iter_type next, ios_base& x,
        E fill, double val) const;
    iter_type put(iter_type next, ios_base& x,
        E fill, long double val) const;
    iter_type put(iter_type next, ios_base& x,
        E fill, const void *val) const;
    iter_type put(iter_type next, ios_base& x,
        E fill, bool val) const;
    static locale::id id;
protected:
    ~num_put();
    virtual iter_type do_put(iter_type next, ios_base& x,
        E fill, long val) const;
    virtual iter_type do_put(iter_type next, ios_base& x,
        E fill, unsigned long val) const;
    virtual iter_type do_put(iter_type next, ios_base& x,
        E fill, double val) const;
    virtual iter_type do_put(iter_type next, ios_base& x,
        E fill, long double val) const;
    virtual iter_type do_put(iter_type next, ios_base& x,
        E fill, const void *val) const;
    virtual iter_type do_put(iter_type next, ios_base& x,
        E fill, bool val) const;
    };

The template class describes an object that can serve as a locale facet, to control conversions of numeric values to sequences of type E.

As with any locale facet, the static object id has an initial stored value of zero. The first attempt to access its stored value stores a unique positive value in id.


num_put::char_type

typedef E char_type;

The type is a synonym for the template parameter E.


num_put::do_put

virtual iter_type do_put(iter_type next, ios_base& x,
    E fill, long val) const;
virtual iter_type do_put(iter_type next, ios_base& x,
    E fill, unsigned long val) const;
virtual iter_type do_put(iter_type next, ios_base& x,
    E fill, double val) const;
virtual iter_type do_put(iter_type nextp ios_base& x,
    E fill, long double val) const;
virtual iter_type do_put(iter_type nextp ios_base& x,
    E fill, const void *val) const;
virtual iter_type do_put(iter_type next, ios_base& x,
    E fill, bool val) const;

The first virtual protected member function generates sequential elements beginning at next to produce an integer output field from the value of val. The function returns an iterator designating the next place to insert an element beyond the generated integer output field.

The integer output field is generated by the same rules used by the print functions for generating a series of char elements to a file. (Each such char element is assumed to map to an equivalent element of type E by a simple, one-to-one, mapping.) Where a print function pads a field with either spaces or the digit 0, however, do_put instead uses fill. The equivalent print conversion specification is determined as follows:

  • If x. flags () & ios_base:: basefield == ios_base:: oct, the conversion specification is lo.
  • If x.flags() & ios_base::basefield == ios_base:: hex, the conversion specification is lx.
  • Otherwise, the conversion specification is ld.

If x. width () is nonzero, a field width of this value is prepended. The function then calls x.width(0) to reset the field width to zero.

Padding occurs only if the minimum number of elements N required to specify the output field is less than x. width (). Such padding consists of a sequence of N - width() copies of fill. Padding then occurs as follows:

  • If x.flags() & ios_base:: adjustfield == ios_base:: left, the flag - is prepended. (Padding occurs after the generated text.)
  • If x.flags() & ios_base::adjustfield == ios_base:: internal, the flag 0 is prepended. (For a numeric output field, padding occurs where the print functions pad with 0.)
  • Otherwise, no additional flag is prepended. (Padding occurs before the generated sequence.)

Finally:

  • If x.flags() & ios_base:: showpos is nonzero, the flag + is prepended to the conversion specification.
  • If x.flags() & ios_base:: showbase is nonzero, the flag # is prepended to the conversion specification.

The format of an integer output field is further determined by the locale facet fac returned by the call use_facet < numpunct <E>(x. getloc ()). Specifically:

  • fac. grouping () determines how digits are grouped to the left of any decimal point
  • fac. thousands_sep () determines the sequence that separates groups of digits to the left of any decimal point

If no grouping constraints are imposed by fac.grouping() (its first element has the value CHAR_MAX) then no instances of fac.thousands_sep() are generated in the output field. Otherwise, separators are inserted after the print conversion occurs.

The second virtual protected member function:

virtual iter_type do_put(iter_type next, ios_base& x,
    E fill, unsigned long val) const;

behaves the same as the first, except that it replaces a conversion specification of ld with lu.

The third virtual protected member function:

virtual iter_type do_put(iter_type next, ios_base& x,
    E fill, double val) const;

behaves the same as the first, except that it produces a floating-point output field from the value of val. fac. decimal_point () determines the sequence that separates the integer digits from the fraction digits. The equivalent print conversion specifier is determined as follows:

  • If x.flags() & ios_base:: floatfield == ios_base:: fixed, the conversion specification is lf.
  • If x.flags() & ios_base::floatfield == ios_base:: scientific, the conversion specification is le. If x.flags() & ios_base:: uppercase is nonzero, e is replaced with E.
  • Otherwise, the conversion specification is lg. If x.flags() & ios_base::uppercase is nonzero, g is replaced with G.

If x.flags() & ios_base::fixed is nonzero, or if x. precision () is greater than zero, a precision with the value x.precision() is prepended to the conversion specification. Any padding behaves the same as for an integer output field. The padding character is fill. Finally:

  • If x.flags() & ios_base:: showpos is nonzero, the flag + is prepended to the conversion specification.
  • If x.flags() & ios_base:: showpoint is nonzero, the flag # is prepended to the conversion specification.

The fourth virtual protected member function:

virtual iter_type do_put(iter_type next, ios_base& x,
    E fill, long double val) const;

behaves the same as the third, except that the qualifier l in the conversion specification is replaced with L.

The fifth virtual protected member function:

virtual iter_type do_put(iter_type next, ios_base& x,
    E fill, const void *val) const;

behaves the same as the first, except that the conversion specification is p, plus any qualifier needed to specify padding.

The sixth virtual protected member function:

virtual iter_type do_put(iter_type next, ios_base& x,
    E fill, bool val) const;

behaves the same as the first, except that it generates a Boolean output field from val.

A Boolean output field takes one of two forms. If x.flags() & ios_base:: boolalpha is false, the generated sequence is either 0 (for false) or 1 (for true). Otherwise, the generated sequence is either fac. falsename () (for false), or fac. truename () (for true).


num_put::put

iter_type put(iter_type next, ios_base& x,
    E fill, long val) const;
iter_type put(iter_type next, ios_base& x,
    E fill, unsigned long val) const;
iter_type put(iter_type iter_type next, ios_base& x,
    E fill, double val) const;
iter_type put(iter_type next, ios_base& x,
    E fill, long double val) const;
iter_type put(iter_type next, ios_base& x,
    E fill, const void *val) const;
iter_type put(iter_type next, ios_base& x,
    E fill, bool val) const;

All member functions return do_put (next, x, fill, val).


num_put::iter_type

typedef InIt iter_type;

The type is a synonym for the template parameter OutIt.


num_put::num_put

explicit num_put(size_t refs = 0);

The constructor initializes its base object with locale:: facet (refs).


numpunct

char_type · decimal_point · do_decimal_point · do_falsename · do_grouping · do_truename · do_thousands_sep · falsename · grouping · numpunct · string_type · thousands_sep · truename

template<class E, class numpunct : public locale::facet {
public:
    typedef E char_type;
    typedef basic_string<E> string_type;
    explicit numpunct(size_t refs = 0);
    E decimal_point() const;
    E thousands_sep() const;
    string grouping() const;
    string_type truename() const;
    string_type falsename() const;
    static locale::id id;
protected:
    ~numpunct();
    virtual E do_decimal_point() const;
    virtual E do_thousands_sep() const;
    virtual string do_grouping() const;
    virtual string_type do_truename() const;
    virtual string_type do_falsename() const;
    };

The template class describes an object that can serve as a locale facet, to describe the sequences of type E used to represent the input fields matched by num_get or the output fields generated by num_get.

As with any locale facet, the static object id has an initial stored value of zero. The first attempt to access its stored value stores a unique positive value in id.


numpunct::char_type

typedef E char_type;

The type is a synonym for the template parameter E.


numpunct::decimal_point

E decimal_point() const;

The member function returns do_decimal_point ().


numpunct::do_decimal_point

E do_decimal_point() const;

The protected virtual member function returns a locale-specific element to use as a decimal point.


numpunct::do_falsename

string_type do_falsename() const;

The protected virtual member function returns a locale-specific sequence to use as a text representation of the value false.


numpunct::do_grouping

string do_grouping() const;

The protected virtual member function returns a locale-specific rule for determining how digits are grouped to the left of any decimal point. The encoding is the same as for lconv::grouping.


numpunct::do_thousands_sep

E do_thousands_sep() const;

The protected virtual member function returns a locale-specific element to use as a group separator to the left of any decimal point.


numpunct::do_truename

string_type do_truename() const;

The protected virtual member function returns a locale-specific sequence to use as a text representation of the value true.


numpunct::falsename

string_type falsename() const;

The member function returns do_falsename ().


numpunct::grouping

string grouping() const;

The member function returns do_grouping ().


numpunct::numpunct

explicit numpunct(size_t refs = 0);

The constructor initializes its base object with locale:: facet (refs).


numpunct::string_type

typedef basic_string<E> string_type;

The type describes a specialization of template class basic_string whose objects can store copies of the punctuation sequences.


numpunct::thousands_sep

E thousands_sep() const;

The member function returns do_thousands_sep ().


numpunct::truename

string_type truename() const;

The member function returns do_truename ().


numpunct_byname

template<class E>
    class numpunct_byname : public numpunct<E> {
public:
    explicit numpunct_byname(const char *s, size_t refs = 0);
protected:
    ~numpunct_byname();
    };

The template class describes an object that can serve as a locale facet of type numpunct <E>. Its behavior is determined by the named locale s. The constructor initializes its base object with numpunct <E>(refs).


time_base

class time_base {
public:
    enum dateorder {no_order, dmy, mdy, ymd, ydm};
    };

The class serves as a base class for facets of template class time_get. It defines just the enumerated type dateorder and several constants of this type. Each of the constants characterizes a different way to order the components of a date. The constants are:

  • no_order specifies no particular order.
  • dmy specifies the order day, month, then year, as in 2 December 1979.
  • mdy specifies the order month, day, then year, as in December 2, 1979.
  • ymd specifies the order year, month, then day, as in 1979/12/2.
  • ydm specifies the order year, day, then month, as in 1979: 2 Dec.


time_get

template<class E, class InIt = istreambuf_iterator<E> >
    class time_get : public locale::facet {
public:
    typedef E char_type;
    typedef InIt iter_type;
    explicit time_get(size_t refs = 0);
    dateorder date_order() const;
    iter_type get_time(iter_type first, iter_type last,
        ios_base& x, ios_base::iostate& st, tm *pt) const;
    iter_type get_date(iter_type first, iter_type last,
        ios_base& x, ios_base::iostate& st, tm *pt) const;
    iter_type get_weekday(iter_type first, iter_type last,
        ios_base& x, ios_base::iostate& st, tm *pt) const;
    iter_type get_month(iter_type first, iter_type last,
        ios_base& x, ios_base::iostate& st, tm *pt) const;
    iter_type get_year(iter_type first, iter_type last,
        ios_base& x, ios_base::iostate& st, tm *pt) const;
    static locale::id id;
protected:
    ~time_get();
    virtual dateorder do_date_order() const;
    virtual iter_type do_get_time(iter_type first, iter_type last,
        ios_base& x, ios_base::iostate& st, tm *pt) const;
    virtual iter_type do_get_date(iter_type first, iter_type last,
        ios_base& x, ios_base::iostate& st, tm *pt) const;
    virtual iter_type do_get_weekday(iter_type first, iter_type last,
        ios_base& x, ios_base::iostate& st, tm *pt) const;
    virtual iter_type do_get_month(iter_type first, iter_type last,
        ios_base& x, ios_base::iostate& st, tm *pt) const;
    virtual iter_type do_get_year(iter_type first, iter_type last,
        ios_base& x, ios_base::iostate& st, tm *pt) const;
    };

The template class describes an object that can serve as a locale facet, to control conversions of sequences of type E to time values.

As with any locale facet, the static object id has an initial stored value of zero. The first attempt to access its stored value stores a unique positive value in id.


time_get::char_type

typedef E char_type;

The type is a synonym for the template parameter E.


time_get::date_order

dateorder date_order() const;

The member function returns date_order ().


time_get::do_date_order

virtual dateorder do_date_order() const;

The virtual protected member function returns a value of type time_base:: dateorder, which describes the order in which date components are matched by do_get_date. In this implementation, the value is time_base:: mdy, corresponding to dates of the form December 2, 1979.


time_get::do_get_date

virtual iter_type do_get_date(iter_type first, iter_type last,
    ios_base& x, ios_base::iostate& st, tm *pt) const;

The virtual protected member function endeavors to match sequential elements beginning at first in the sequence [first, last) until it has recognized a complete, nonempty date input field. If successful, it converts this field to its equivalent value as the components tm::tm_mon, tm::tm_day, and tm::tm_year, and stores the results in pt->tm_mon, pt->tm_day, and pt->tm_year, respectively. It returns an iterator designating the first element beyond the date input field. Otherwise, the function sets ios_base::failbit in st. It returns an iterator designating the first element beyond any prefix of a valid date input field. In either case, if the return value equals last, the function sets ios_base::eofbit in st.

In this implementation, the date input field has the form MMM DD, YYYY, where:

  • MMM is matched by calling get_month, giving the month.
  • DD is a sequence of decimal digits whose corresponding numeric value must be in the range [1, 31], giving the day of the month.
  • YYYY is matched by calling get_year, giving the year.
  • The literal spaces and commas must match corresponding elements in the input sequence.


time_get::do_get_month

virtual iter_type do_get_month(iter_type first, iter_type last,
    ios_base& x, ios_base::iostate& st, tm *pt) const;

The virtual protected member function endeavors to match sequential elements beginning at first in the sequence [first, last) until it has recognized a complete, nonempty month input field. If successful, it converts this field to its equivalent value as the component tm::tm_mon, and stores the result in pt->tm_mon. It returns an iterator designating the first element beyond the month input field. Otherwise, the function sets ios_base::failbit in st. It returns an iterator designating the first element beyond any prefix of a valid month input field. In either case, if the return value equals last, the function sets ios_base::eofbit in st.

The month input field is a sequence that matches the longest of a set of locale-specific sequences, such as Jan, January, Feb, February. The converted value is the number of months since January.


time_get::do_get_time

virtual iter_type do_get_time(iter_type first, iter_type last,
    ios_base& x, ios_base::iostate& st, tm *pt) const;

The virtual protected member function endeavors to match sequential elements beginning at first in the sequence [first, last) until it has recognized a complete, nonempty time input field. If successful, it converts this field to its equivalent value as the components tm::tm_hour, tm::tm_min, and tm::tm_sec, and stores the results in pt->tm_hour, pt->tm_min, and pt->tm_sec, respectively. It returns an iterator designating the first element beyond the time input field. Otherwise, the function sets ios_base::failbit in st. It returns an iterator designating the first element beyond any prefix of a valid time input field. In either case, if the return value equals last, the function sets ios_base::eofbit in st.

In this implementation, the time input field has the form HH:MM:SS, where:

  • HH is a sequence of decimal digits whose corresponding numeric value must be in the range [0, 24), giving the hour of the day.
  • MM is a sequence of decimal digits whose corresponding numeric value must be in the range [0, 60), giving the minutes past the hour.
  • SS is a sequence of decimal digits whose corresponding numeric value must be in the range [0, 60), giving the seconds past the minute.
  • The literal colons must match corresponding elements in the input sequence.


time_get::do_get_weekday

virtual iter_type do_get_weekday(iter_type first, iter_type last,
    ios_base& x, ios_base::iostate& st, tm *pt) const;

The virtual protected member function endeavors to match sequential elements beginning at first in the sequence [first, last) until it has recognized a complete, nonempty weekday input field. If successful, it converts this field to its equivalent value as the component tm::tm_wday, and stores the result in pt->tm_wday. It returns an iterator designating the first element beyond the weekday input field. Otherwise, the function sets ios_base::failbit in st. It returns an iterator designating the first element beyond any prefix of a valid weekday input field. In either case, if the return value equals last, the function sets ios_base::eofbit in st.

The weekday input field is a sequence that matches the longest of a set of locale-specific sequences, such as Sun, Sunday, Mon, Monday. The converted value is the number of days since Sunday.


time_get::do_get_year

virtual iter_type do_get_year(iter_type first, iter_type last,
    ios_base& x, ios_base::iostate& st, tm *pt) const;

The virtual protected member function endeavors to match sequential elements beginning at first in the sequence [first, last) until it has recognized a complete, nonempty year input field. If successful, it converts this field to its equivalent value as the component tm::tm_year, and stores the result in pt->tm_year. It returns an iterator designating the first element beyond the year input field. Otherwise, the function sets ios_base::failbit in st. It returns an iterator designating the first element beyond any prefix of a valid year input field. In either case, if the return value equals last, the function sets ios_base::eofbit in st.

The year input field is a sequence of decimal digits whose corresponding numeric value must be in the range [1900, 2036). The stored value is this value minus 1900. In this implementation, a numeric value in the range [0, 136) is also permissible. It is stored unchanged.


time_get::get_date

iter_type get_date(iter_type first, iter_type last,
    ios_base& x, ios_base::iostate& st, tm *pt) const;

The member function returns do_get_date (first, last, x, st, pt).


time_get::get_month

iter_type get_month(iter_type first, iter_type last,
    ios_base& x, ios_base::iostate& st, tm *pt) const;

The member function returns do_get_month (first, last, x, st, pt).


time_get::get_time

iter_type get_time(iter_type first, iter_type last,
    ios_base& x, ios_base::iostate& st, tm *pt) const;

The member function returns do_get_time (first, last, x, st, pt).


time_get::get_weekday

iter_type get_weekday(iter_type first, iter_type last,
    ios_base& x, ios_base::iostate& st, tm *pt) const;

The member function returns do_get_weekday (first, last, x, st, pt).


time_get::get_year

iter_type get_year(iter_type first, iter_type last,
    ios_base& x, ios_base::iostate& st, tm *pt) const;

The member function returns do_get_year (first, last, x, st, pt).


time_get::iter_type

typedef InIt iter_type;

The type is a synonym for the template parameter InIt.


time_get::time_get

explicit time_get(size_t refs = 0);

The constructor initializes its base object with locale:: facet (refs).


time_get_byname

template<class E, class InIt>
    class time_get_byname : public time_get<E, InIt> {
public:
    explicit time_get_byname(const char *s, size_t refs = 0);
protected:
    ~time_get_byname();
    };

The template class describes an object that can serve as a locale facet of type time_get <E, InIt>. Its behavior is determined by the named locale s. The constructor initializes its base object with time_get <E, InIt>(refs).


time_put

template<class E, class OutIt = ostreambuf_iterator<E> >
    class time_put : public locale::facet {
public:
    typedef E char_type;
    typedef OutIt iter_type;
    explicit time_put(size_t refs = 0);
    iter_type put(iter_type next, ios_base& x,
        tm *pt, char fmt, char mod = 0) const;
    iter_type put(iter_type next, ios_base& x,
        tm *pt, const E *first, const E *last) const;
    static locale::id id;
protected:
    ~time_put();
    virtual iter_type do_put(iter_type next, ios_base& x,
        tm *pt, char fmt, char mod = 0) const;
    };

The template class describes an object that can serve as a locale facet, to control conversions of time values to sequences of type E.

As with any locale facet, the static object id has an initial stored value of zero. The first attempt to access its stored value stores a unique positive value in id.


time_put::char_type

typedef E char_type;

The type is a synonym for the template parameter E.


time_put::do_put

virtual iter_type do_put(iter_type next, ios_base& x,
    tm *pt, char fmt, char mod = 0) const;

The virtual protected member function generates sequential elements beginning at next from time values stored in the object *pt, of type tm. The function returns an iterator designating the next place to insert an element beyond the generated output.

The output is generated by the same rules used by strftime, with a last argument of pt, for generating a series of char elements into an array. (Each such char element is assumed to map to an equivalent element of type E by a simple one-to-one mapping.) If mod equals zero, the effective format is "%F", where F equals fmt. Otherwise, the effective format is "%MF", where M equals mod.


time_put::put

iter_type put(iter_type next, ios_base& x,
    tm *pt, char fmt, char mod = 0) const;
iter_type put(iter_type next, ios_base& x,
    tm *pt, const E *first, const E *last) const;

The first member function returns do_put (next, x, pt, fmt, mod). The second member function copies to *next++ any element in the interval [first, last) other than a percent (%). For a percent followed by a character C in the interval [first, last), the function instead evaluates next = do_put(next, x, pt, C, 0) and skips past C. If, however, C is a qualifier character from the set EOQ#, followed by a character C2 in the interval [first, last), the function instead evaluates next = do_put(next, x, pt, C2, C) and skips past C2.


time_put::iter_type

typedef InIt iter_type;

The type is a synonym for the template parameter OutIt.


time_put::time_put

explicit time_put(size_t refs = 0);

The constructor initializes its base object with locale:: facet (refs).


time_put_byname

template<class E, class OutIt>
    class time_put_byname : public time_put<E, OutIt> {
public:
    explicit time_put_byname(const char *s, size_t refs = 0);
protected:
    ~time_put_byname();
    };

The template class describes an object that can serve as a locale facet of type time_put <E, OutIt>. Its behavior is determined by the named locale s. The constructor initializes its base object with time_put <E, OutIt>(refs).


tolower

template<class E>
    E tolower(E c, const locale& loc) const;

The template function returns use_facet < ctype <E> >(loc). tolower (c).


toupper

template<class E>
    E toupper(E c, const locale& loc) const;

The template function returns use_facet < ctype <E> >(loc). toupper (c).


use_facet

template<class Facet>
    const Facet& use_facet(const locale& loc,
        const Facet *fac, bool make_it);

The template function returns a reference to the locale facet of class Facet listed within the locale object loc. If no such object is listed, the function throws an object of class bad_cast.

In this implementation, make_it instructs the function to generate the locale facet on demand. But you should write _USE(loc, Facet), or _USEFAC(loc, Facet) in place of use_facet(loc, (Facet *)0, make_it), because the second and third parameters are a nonstandard extension. The former is strongly preferred when looking up a facet that should always be present -- it generates the requested facet on demand, if necessary. The latter will report that the locale initially constructed by locale () has no facets.


 <map>

<map>

namespace std {
template<class Key, class T, class Pred, class A>
    class map;
template<class Key, class T, class Pred, class A>
    class multimap;
//    TEMPLATE FUNCTIONS
template<class Key, class T, class Pred, class A>
    bool operator==(
        const map<Key, T, Pred, A>& lhs,
        const map<Key, T, Pred, A>& rhs);
template<class Key, class T, class Pred, class A>
    bool operator==(
        const multimap<Key, T, Pred, A>& lhs,
        const multimap<Key, T, Pred, A>& rhs);
template<class Key, class T, class Pred, class A>
    bool operator!=(
        const map<Key, T, Pred, A>& lhs,
        const map<Key, T, Pred, A>& rhs);
template<class Key, class T, class Pred, class A>
    bool operator!=(
        const multimap<Key, T, Pred, A>& lhs,
        const multimap<Key, T, Pred, A>& rhs);
template<class Key, class T, class Pred, class A>
    bool operator<(
        const map<Key, T, Pred, A>& lhs,
        const map<Key, T, Pred, A>& rhs);
template<class Key, class T, class Pred, class A>
    bool operator<(
        const multimap<Key, T, Pred, A>& lhs,
        const multimap<Key, T, Pred, A>& rhs);
template<class Key, class T, class Pred, class A>
    bool operator>(
        const map<Key, T, Pred, A>& lhs,
        const map<Key, T, Pred, A>& rhs);
template<class Key, class T, class Pred, class A>
    bool operator>(
        const multimap<Key, T, Pred, A>& lhs,
        const multimap<Key, T, Pred, A>& rhs);
template<class Key, class T, class Pred, class A>
    bool operator<=(
        const map<Key, T, Pred, A>& lhs,
        const map<Key, T, Pred, A>& rhs);
template<class Key, class T, class Pred, class A>
    bool operator<=(
        const multimap<Key, T, Pred, A>& lhs,
        const multimap<Key, T, Pred, A>& rhs);
template<class Key, class T, class Pred, class A>
    bool operator>=(
        const map<Key, T, Pred, A>& lhs,
        const map<Key, T, Pred, A>& rhs);
template<class Key, class T, class Pred, class A>
    bool operator>=(
        const multimap<Key, T, Pred, A>& lhs,
        const multimap<Key, T, Pred, A>& rhs);
template<class Key, class T, class Pred, class A>
    void swap(
        const map<Key, T, Pred, A>& lhs,
        const map<Key, T, Pred, A>& rhs);
template<class Key, class T, class Pred, class A>
    void swap(
        const multimap<Key, T, Pred, A>& lhs,
        const multimap<Key, T, Pred, A>& rhs);
    };

Include the STL standard header <map> to define the container template classes map and multimap, and their supporting templates.


map

allocator_type · begin · clear · const_iterator · const_reference · const_reverse_iterator · count · difference_type · empty · end · equal_range · erase · find · get_allocator · insert · iterator · key_comp · key_compare · key_type · lower_bound · map · max_size · operator[] · rbegin · reference · referent_type · rend · reverse_iterator · size · size_type · swap · upper_bound · value_comp · value_compare · value_type

template<class Key, class T, class Pred = less<Key>, class A = allocator<T> >
    class map {
public:
    typedef Key key_type;
    typedef T referent_type;
    typedef Pred key_compare;
    typedef A allocator_type;
    typedef pair<const Key, T> value_type;
    class value_compare;
    typedef A::size_type size_type;
    typedef A::difference_type difference_type;
    typedef A::rebind<value_type>::other::reference reference;
    typedef A::rebind<value_type>::other::const_reference const_reference;
    typedef T0 iterator;
    typedef T1 const_iterator;
    typedef reverse_bidirectional_iterator<iterator,
        value_type, reference, A::pointer,
            difference_type> reverse_iterator;
    typedef reverse_bidirectional_iterator<const_iterator,
        value_type, const_reference, A::const_pointer,
            difference_type> const_reverse_iterator;
    explicit map(const Pred& comp = Pred(), const A& al = A());
    map(const map& x);
    map(const value_type *first, const value_type *last,
        const Pred& comp = Pred(),
            const A& al = A());
    iterator begin();
    const_iterator begin() const;
    iterator end();
    iterator end() const;
    reverse_iterator rbegin();
    const_reverse_iterator rbegin() const;
    reverse_iterator rend();
    const_reverse_iterator rend() const;
    size_type size() const;
    size_type max_size() const;
    bool empty() const;
    A get_allocator() const;
    A::reference operator[](const Key& key);
    pair<iterator, bool> insert(const value_type& x);
    iterator insert(iterator it, const value_type& x);
    void insert(const value_type *first, const value_type *last);
    iterator erase(iterator it);
    iterator erase(iterator first, iterator last);
    size_type erase(const Key& key);
    void clear();
    void swap(map x);
    key_compare key_comp() const;
    value_compare value_comp() const;
    iterator find(const Key& key);
    const_iterator find(const Key& key) const;
    size_type count(const Key& key) const;
    iterator lower_bound(const Key& key);
    const_iterator lower_bound(const Key& key) const;
    iterator upper_bound(const Key& key);
    const_iterator upper_bound(const Key& key) const;
    pair<iterator, iterator> equal_range(const Key& key);
    pair<const_iterator, const_iterator>
        equal_range(const Key& key) const;
protected:
    A allocator;
    };

The template class describes an object that controls a varying-length sequence of elements of type pair <const Key, T>. The first element of each pair is the sort key and the second is its associated value. The sequence is represented in a way that permits lookup, insertion, and removal of an arbitrary element with a number of operations proportional to the logarithm of the number of elements in the sequence (logarithmic time). Moreover, inserting an element invalidates no iterators, and removing an element invalidates only those iterators that point at the removed element.

The object orders the sequence it controls by calling a stored function object of type Pred. You access this stored object by calling the member function key_comp (). Such a function object must impose a total order on sort keys. For any element x that precedes y in the sequence, key_comp()(y. first , x.first) is false. (For the default function object less <Key>, sort keys never decrease in value.) Unlike template class multimap, an object of template class map ensures that key_comp()(x.first, y.first) is true. (Each key is unique.)

The object allocates and frees storage for the sequence it controls through a protected object named allocator, of class A. Such an allocator object must have the same external interface as an object of template class allocator. Note that allocator is not copied when the object is assigned.


map::allocator_type

typedef A allocator_type;

The type is a synonym for the template parameter A.


map::begin

const_iterator begin() const;
iterator begin();

The member function returns a bidirectional iterator that points at the first element of the sequence (or just beyond the end of an empty sequence).


map::clear

void clear() const;

The member function calls erase ( begin (), end ()).

See the related sample program.


map::const_iterator

typedef T1 const_iterator;

The type describes an object that can serve as a constant bidirectional iterator for the controlled sequence. It is described here as a synonym for the unspecified type T1.


map::const_reference

typedef A::rebind<value_type>::other::const_reference const_reference;

The type describes an object that can serve as a constant reference to an element of the controlled sequence.


map::const_reverse_iterator

typedef reverse_bidirectional_iterator<const_iterator,
    value_type, const_reference, A::const_pointer,
        difference_type> const_reverse_iterator;

The type describes an object that can serve as a constant reverse bidirectional iterator for the controlled sequence.


map::count

size_type count(const Key& key) const;

The member function returns the number of elements x in the range [ lower_bound (key), upper_bound (key)).


map::difference_type

typedef A::difference_type difference_type;

The signed integer type describes an object that can represent the difference between the addresses of any two elements in the controlled sequence.


map::empty

bool empty() const;

The member function returns true for an empty controlled sequence.


map::end

const_iterator end() const;
iterator end();

The member function returns a bidirectional iterator that points just beyond the end of the sequence.

See the related sample program.


map::equal_range

pair<iterator, iterator> equal_range(const Key& key);
pair<const_iterator, const_iterator>
    equal_range(const Key& key) const;

The member function returns a pair of iterators x such that x.first == lower_bound (key) and x.second == upper_bound (key).


map::erase

iterator erase(iterator it);
iterator erase(iterator first, iterator last);
size_type erase(const Key& key);

The first member function removes the element of the controlled sequence pointed to by it. The second member function removes the elements in the interval [first, last). Both return an iterator that designates the first element remaining beyond any elements removed, or end () if no such element exists.

The third member function removes the elements with sort keys in the range [ lower_bound (key), upper_bound (key)). It returns the number of elements it removes.

See the related sample program.


map::find

iterator find(const Key& key);
const_iterator find(const Key& key) const;

The member function returns an iterator that designates the earliest element in the controlled sequence whose sort key equals key. If no such element exists, the iterator equals end ().

See the related sample program.


map::get_allocator

A get_allocator() const;

The member function returns allocator.


map::insert

pair<iterator, bool> insert(const value_type& x);
iterator insert(iterator it, const value_type& x);
void insert(const value_type *first, const value_type *last);

The first member function determines whether an element y exists in the sequence whose key matches that of x. (The keys match if ! key_comp ()(x. first , y.first) && !key_comp()(y.first, x.first).) If not, it creates such an element y and initializes it with x. The function then determines the iterator it that designates y. If an insertion occurred, the function returns pair (it, true). Otherwise, it returns pair(it, false).

The second member function returns insert(x), using it as a starting place within the controlled sequence to search for the insertion point. (Insertion can occur in amortized constant time, instead of logarithmic time, if the insertion point immediately follows it.) The third member function inserts the sequence of element values in the range [first, last).

In this implementation, if a translator does not support member template functions, the template:

template<class InIt>
    void insert(InIt first, InIt last);

is replaced by:

void insert(const value_type *first, const value_type *last);

See the related sample program.


map::iterator

typedef T0 iterator;

The type describes an object that can serve as a bidirectional iterator for the controlled sequence. It is described here as a synonym for the unspecified type T0.


map::key_comp

key_compare key_comp() const;

The member function returns the stored function object that determines the order of elements in the controlled sequence. The stored object determines the member function:

bool operator(const Key& x, const Key& y);

which returns true if x strictly precedes y in the sort order.


map::key_compare

typedef Pred key_compare;

The type describes a function object that can compare two sort keys to determine the relative order of any two elements in the controlled sequence.


map::key_type

typedef Key key_type;

The type describes the sort key object stored in each element of the controlled sequence.


map::lower_bound

iterator lower_bound(const Key& key);
const_iterator lower_bound(const Key& key) const;

The member function returns an iterator that designates the earliest element x in the controlled sequence for which key_comp ()(x. first , key) is false.

If no such element exists, the function returns end ().


map::map

explicit map(const Pred& comp = Pred(), const A& al = A());
map(const map& x);
map(const value_type *first, const value_type *last,
    const Pred& comp = Pred(), const A& al = A());

The constructors with an argument named comp store the function object so that it can be later returned by calling key_comp (). All constructors also store the allocator object al (or, for the copy constructor, x. get_allocator ()) in allocator and initialize the controlled sequence. The first constructor specifies an empty initial controlled sequence. The second constructor specifies a copy of the sequence controlled by x. The last constructor specifies the sequence of element values [first, last).

In this implementation, if a translator does not support member template functions, the template:

template<class InIt>
    map(InIt first, InIt last,
        const Pred& comp = Pred(), const A& al = A());

is replaced by:

map(const value_type *first, const value_type *last,
    const Pred& comp = Pred(), const A& al = A());


map::max_size

size_type max_size() const;

The member function returns the length of the longest sequence that the object can control.

See the related sample program.


map::operator[]

A::reference operator[](const Key& key);

The member function determines the iterator it as the return value of insert ( value_type (key, T()). (It inserts an element with the specified key if no such element exists.) It then returns a reference to (*it). second.


map::rbegin

const_reverse_iterator rbegin() const;
reverse_iterator rbegin();

The member function returns a reverse bidirectional iterator that points just beyond the end of the controlled sequence. Hence, it designates the beginning of the reverse sequence.


map::reference

typedef A::rebind<value_type>::other::reference reference;

The type describes an object that can serve as a reference to an element of the controlled sequence.


map::referent_type

typedef T referent_type;

The type is a synonym for the template parameter T.


map::rend

const_reverse_iterator rend() const;
reverse_iterator rend();

The member function returns a reverse bidirectional iterator that points at the first element of the sequence (or just beyond the end of an empty sequence). Hence, it designates the end of the reverse sequence.


map::reverse_iterator

typedef reverse_bidirectional_iterator<iterator,
    value_type, reference, A::pointer,
        difference_type> reverse_iterator;

The type describes an object that can serve as a reverse bidirectional iterator for the controlled sequence.


map::size

size_type size() const;

The member function returns the length of the controlled sequence.

See the related sample program.


map::size_type

typedef A::size_type size_type;

The unsigned integer type describes an object that can represent the length of any controlled sequence.


map::swap

void swap(map& str);

The member function swaps the controlled sequences between *this and str. If allocator == str.allocator, it does so in constant time. Otherwise, it performs a number of element assignments and constructor calls proportional to the number of elements in the two controlled sequences.


map::upper_bound

iterator upper_bound(const Key& key);
const_iterator upper_bound(const Key& key) const;

The member function returns an iterator that designates the earliest element x in the controlled sequence for which key_comp ()(key, x. first ) is true.

If no such element exists, the function returns end ().


map::value_comp

value_compare value_comp() const;

The member function returns a function object that determines the order of elements in the controlled sequence.


map::value_compare

class value_compare
    : public binary_function<value_type, value_type, bool> {
public:
    bool operator()(const value_type& x, const value_type& y)
        {return (comp(x.first, x.second)); }
protected:
    value_compare(key_compare pr)
        : comp(pr) {}
    key_compare comp;
    };

The type describes a function object that can compare the sort keys in two elements to determine their relative order in the controlled sequence. The function object stores an object comp of type key_type. The member function operator() uses this object to compare the sort-key components of two elements.


map::value_type

typedef pair<const Key, T> value_type;

The type describes an element of the controlled sequence.


multimap

allocator_type · begin · clear · const_iterator · const_reference · const_reverse_iterator · count · difference_type · empty · end · equal_range · erase · find · get_allocator · insert · iterator · key_comp · key_compare · key_type · lower_bound · max_size · multimap · rbegin · reference · referent_type · rend · reverse_iterator · size · size_type · swap · upper_bound · value_comp · value_compare · value_type

template<class Key, class T, class Pred = less<Key>, class A = allocator<T> >
    class multimap {
public:
    typedef Key key_type;
    typedef T referent_type;
    typedef Pred key_compare;
    typedef A allocator_type;
    typedef pair<const Key, T> value_type;
    class value_compare;
    typedef A::size_type size_type;
    typedef A::difference_type difference_type;
    typedef A::rebind<value_type>::other::reference reference;
    typedef A::rebind<value_type>::other::const_reference const_reference;
    typedef T0 iterator;
    typedef T1 const_iterator;
    typedef reverse_bidirectional_iterator<iterator,
        value_type, reference, A::pointer,
            difference_type> reverse_iterator;
    typedef reverse_bidirectional_iterator<const_iterator,
        value_type, const_reference, A::const_pointer,
            difference_type> const_reverse_iterator;
    explicit multimap(const Pred& comp = Pred(), const A& al = A());
    multimap(const multimap& x);
    multimap(const value_type *first, const value_type *last,
        const Pred& comp = Pred(), const A& al = A());
    iterator begin();
    const_iterator begin() const;
    iterator end();
    iterator end() const;
    reverse_iterator rbegin();
    const_reverse_iterator rbegin() const;
    reverse_iterator rend();
    const_reverse_iterator rend() const;
    size_type size() const;
    size_type max_size() const;
    bool empty() const;
    A get_allocator() const;
    iterator insert(const value_type& x);
    iterator insert(iterator it, const value_type& x);
    void insert(const value_type *first, const value_type *last);
    iterator erase(iterator it);
    iterator erase(iterator first, iterator last);
    size_type erase(const Key& key);
    void clear();
    void swap(multimap x);
    key_compare key_comp() const;
    value_compare value_comp() const;
    iterator find(const Key& key);
    const_iterator find(const Key& key) const;
    size_type count(const Key& key) const;
    iterator lower_bound(const Key& key);
    const_iterator lower_bound(const Key& key) const;
    iterator upper_bound(const Key& key);
    const_iterator upper_bound(const Key& key) const;
    pair<iterator, iterator> equal_range(const Key& key);
    pair<const_iterator, const_iterator>
        equal_range(const Key& key) const;
protected:
    A allocator;
    };

The template class describes an object that controls a varying-length sequence of elements of type pair <const Key, T>. The first element of each pair is the sort key and the second is its associated value. The sequence is represented in a way that permits lookup, insertion, and removal of an arbitrary element with a number of operations proportional to the logarithm of the number of elements in the sequence (logarithmic time). Moreover, inserting an element invalidates no iterators, and removing an element invalidates only those iterators that point at the removed element.

The object orders the sequence it controls by calling a stored function object of type Pred. You access this stored object by calling the member function key_comp (). Such a function object must impose a total order on sort keys. For any element x that precedes y in the sequence, key_comp()(y. first , x.first) is false. (For the default function object less <Key>, sort keys never decrease in value.) Unlike template class map, an object of template class multimap does not ensure that key_comp()(x.first, y.first) is true. (Keys need not be unique.)

The object allocates and frees storage for the sequence it controls through a protected object named allocator, of class A. Such an allocator object must have the same external interface as an object of template class allocator. Note that allocator is not copied when the object is assigned.


multimap::allocator_type

typedef A allocator_type;

The type is a synonym for the template parameter A.


multimap::begin

const_iterator begin() const;
iterator begin();

The member function returns a bidirectional iterator that points at the first element of the sequence (or just beyond the end of an empty sequence).


multimap::clear

void clear() const;

The member function calls erase ( begin (), end ()).


multimap::const_reference

typedef A::rebind<value_type>::other::const_reference const_reference;

The type describes an object that can serve as a constant reference to an element of the controlled sequence.


multimap::const_iterator

typedef T1 const_iterator;

The type describes an object that can serve as a constant bidirectional iterator for the controlled sequence. It is described here as a synonym for the unspecified type T1.


multimap::count

size_type count(const Key& key) const;

The member function returns the number of elements x in the range [ lower_bound (key), upper_bound (key)).


multimap::const_reverse_iterator

typedef reverse_bidirectional_iterator<const_iterator,
    value_type, const_reference, A::const_pointer,
        difference_type> const_reverse_iterator;

The type describes an object that can serve as a constant reverse bidirectional iterator for the controlled sequence.


multimap::difference_type

typedef A::difference_type difference_type;

The signed integer type describes an object that can represent the difference between the addresses of any two elements in the controlled sequence.


multimap::empty

bool empty() const;

The member function returns true for an empty controlled sequence.


multimap::end

const_iterator end() const;
iterator end();

The member function returns a bidirectional iterator that points just beyond the end of the sequence.


multimap::equal_range

pair<iterator, iterator> equal_range(const Key& key);
pair<const_iterator, const_iterator>
    equal_range(const Key& key) const;

The member function returns a pair of iterators x such that x.first == lower_bound (key) and x.second == upper_bound (key).


multimap::erase

iterator erase(iterator it);
iterator erase(iterator first, iterator last);
size_type erase(const Key& key);

The first member function removes the element of the controlled sequence pointed to by it. The second member function removes the elements in the range [first, last). Both return an iterator that designates the first element remaining beyond any elements removed, or end () if no such element exists.

The third member removes the elements with sort keys in the range [ lower_bound (key), upper_bound (key)). It returns the number of elements it removes.


multimap::find

iterator find(const Key& key);
const_iterator find(const Key& key) const;

The member function returns an iterator that designates the earliest element in the controlled sequence whose sort key equals key. If no such element exists, the iterator equals end ().


multimap::get_allocator

A get_allocator() const;

The member function returns allocator.


multimap::insert

iterator insert(const value_type& x);
iterator insert(iterator it, const value_type& x);
void insert(const value_type *first, const value_type *last);

The first member function inserts the element x in the controlled sequence, then returns the iterator that designates the inserted element. The second member function returns insert(x), using it as a starting place within the controlled sequence to search for the insertion point. (Insertion can occur in amortized constant time, instead of logarithmic time, if the insertion point immediately follows it.) The third member function inserts the sequence of element values in the range [first, last).

In this implementation, if a translator does not support member template functions, the template:

template<class InIt>
    void insert(InIt first, InIt last);

is replaced by:

void insert(const value_type *first, const value_type *last);


multimap::iterator

typedef T0 iterator;

The type describes an object that can serve as a bidirectional iterator for the controlled sequence. It is described here as a synonym for the unspecified type T0.


multimap::key_comp

key_compare key_comp() const;

The member function returns the stored function object that determines the order of elements in the controlled sequence. The stored object defines the member function:

bool operator(const Key& x, const Key& y);

which returns true if x strictly precedes y in the sort order.


multimap::key_compare

typedef Pred key_compare;

The type describes a function object that can compare two sort keys to determine the relative order of any two elements in the controlled sequence.


multimap::key_type

typedef Key key_type;

The type describes the sort key object stored in each element of the controlled sequence.


multimap::lower_bound

iterator lower_bound(const Key& key);
const_iterator lower_bound(const Key& key) const;

The member function returns an iterator that designates the earliest element x in the controlled sequence for which key_comp ()(x. first , key) is false.

If no such element exists, the function returns end ().


multimap::max_size

size_type max_size() const;

The member function returns the length of the longest sequence that the object can control.


multimap::multimap

explicit multimap(const Pred& comp = Pred(), const A& al = A());
multimap(const multimap& x);
multimap(const value_type *first, const value_type *last,
    const Pred& comp = Pred(), const A& al = A());

The constructors with an argument named comp store the function object so that it can be later returned by calling key_comp (). All constructors also store the allocator object al (or, for the copy constructor, x. get_allocator ()) in allocator and initialize the controlled sequence. The first constructor specifies an empty initial controlled sequence. The second constructor specifies a copy of the sequence controlled by x. The member template constructor specifies the sequence of element values [first, last).

In this implementation, if a translator does not support member template functions, the template:

template<class InIt>
    multimap(InIt first, InIt last,
        const Pred& comp = Pred(), const A& al = A());

is replaced by:

multimap(const value_type *first, const value_type *last,
    const Pred& comp = Pred(), const A& al = A());


multimap::rbegin

const_reverse_iterator rbegin() const;
reverse_iterator rbegin();

The member function returns a reverse bidirectional iterator that points just beyond the end of the controlled sequence. Hence, it designates the beginning of the reverse sequence.


multimap::reference

typedef A::rebind<value_type>::other::reference reference;

The type describes an object that can serve as a reference to an element of the controlled sequence.


multimap::referent_type

typedef T referent_type;

The type is a synonym for the template parameter T.


multimap::rend

const_reverse_iterator rend() const;
reverse_iterator rend();

The member function returns a reverse bidirectional iterator that points at the first element of the sequence (or just beyond the end of an empty sequence). Hence, it designates the end of the reverse sequence.


multimap::reverse_iterator

typedef reverse_bidirectional_iterator<iterator,
    value_type, reference, A::pointer,
        difference_type> reverse_iterator;

The type describes an object that can serve as a reverse bidirectional iterator for the controlled sequence.


multimap::size

size_type size() const;

The member function returns the length of the controlled sequence.


multimap::size_type

typedef A::size_type size_type;

The unsigned integer type describes an object that can represent the length of any controlled sequence.


multimap::swap

void swap(multimap& str);

The member function swaps the controlled sequences between *this and str. If allocator == str.allocator, it does so in constant time. Otherwise, it performs a number of element assignments and constructor calls proportional to the number of elements in the two controlled sequences.


multimap::upper_bound

iterator upper_bound(const Key& key);
const_iterator upper_bound(const Key& key) const;

The member function returns an iterator that designates the earliest element x in the controlled sequence for which key_comp ()(key, x. first ) is true.

If no such element exists, the function returns end ().


multimap::value_comp

value_compare value_comp() const;

The member function returns a function object that determines the order of elements in the controlled sequence.


multimap::value_compare

class value_compare
    : public binary_function<value_type, value_type, bool> {
public:
    bool operator()(const value_type& x, const value_type& y)
        {return (comp(x.first, x.second)); }
protected:
    value_compare(key_compare pr)
        : comp(pr) {}
    key_compare comp;
    };

The type describes a function object that can compare the sort keys in two elements to determine their relative order in the controlled sequence. The function object stores an object comp of type key_type. The member function operator() uses this object to compare the sort-key components of two elements.


multimap::value_type

typedef pair<const Key, T> value_type;

The type describes an element of the controlled sequence.


operator!=

template<class Key, class T, class Pred, class A>
    bool operator!=(
        const map <Key, T, Pred, A>& lhs,
        const map <Key, T, Pred, A>& rhs);
template<class Key, class T, class Pred, class A>
    bool operator!=(
        const multimap <Key, T, Pred, A>& lhs,
        const multimap <Key, T, Pred, A>& rhs);

The template function returns !(lhs == rhs).


operator==

template<class Key, class T, class Pred, class A>
    bool operator==(
        const map <Key, T, Pred, A>& lhs,
        const map <Key, T, Pred, A>& rhs);
template<class Key, class T, class Pred, class A>
    bool operator==(
        const multimap <Key, T, Pred, A>& lhs,
        const multimap <Key, T, Pred, A>& rhs);

The first template function overloads operator== to compare two objects of template class map. The second template function overloads operator== to compare two objects of template class multimap. Both functions return lhs. size () == rhs.size() && equal (lhs. begin (), lhs. end (), rhs.begin()).


operator<

template<class Key, class T, class Pred, class A>
    bool operator<(
        const map <Key, T, Pred, A>& lhs,
        const map <Key, T, Pred, A>& rhs);
template<class Key, class T, class Pred, class A>
    bool operator<(
        const multimap <Key, T, Pred, A>& lhs,
        const multimap <Key, T, Pred, A>& rhs);

The first template function overloads operator< to compare two objects of template class map. The second template function overloads operator< to compare two objects of template class multimap. Both functions return lexicographical_compare (lhs. begin (), lhs. end (), rhs.begin(), rhs.end()).


operator<=

template<class Key, class T, class Pred, class A>
    bool operator<=(
        const map <Key, T, Pred, A>& lhs,
        const map <Key, T, Pred, A>& rhs);
template<class Key, class T, class Pred, class A>
    bool operator<=(
        const multimap <Key, T, Pred, A>& lhs,
        const multimap <Key, T, Pred, A>& rhs);

The template function returns !(rhs < lhs).


operator>

template<class Key, class T, class Pred, class A>
    bool operator>(
        const map <Key, T, Pred, A>& lhs,
        const map <Key, T, Pred, A>& rhs);
template<class Key, class T, class Pred, class A>
    bool operator>(
        const multimap <Key, T, Pred, A>& lhs,
        const multimap <Key, T, Pred, A>& rhs);

The template function returns rhs < lhs.


operator>=

template<class Key, class T, class Pred, class A>
    bool operator>=(
        const map <Key, T, Pred, A>& lhs,
        const map <Key, T, Pred, A>& rhs);
template<class Key, class T, class Pred, class A>
    bool operator>=(
        const multimap <Key, T, Pred, A>& lhs,
        const multimap <Key, T, Pred, A>& rhs);

The template function returns !(lhs < rhs).


swap

template<class Key, class T, class Pred, class A>
    void swap(
        const map <Key, T, Pred, A>& lhs,
        const map <Key, T, Pred, A>& rhs);
template<class Key, class T, class Pred, class A>
    void swap(
        const multimap <Key, T, Pred, A>& lhs,
        const multimap <Key, T, Pred, A>& rhs);

The template function executes lhs. swap (rhs).


 <memory>

<memory>

namespace std {
//  TEMPLATE CLASSES
template<class T>
    class allocator;
class allocator<void>;
template<class FwdIt, class T>
    class raw_storage_iterator;
template<class T>
    class auto_ptr;
//  TEMPLATE OPERATORS
template<class T>
    bool operator==(allocator<T>& lhs,
        allocator<T>& rhs);
template<class T>
    bool operator!=(allocator<T>& lhs,
        allocator<T>& rhs);
template<class T>
    void operator delete(void *p, size_t n, allocator& al);
template<class T>
    void *operator new(size_t n, allocator& al);
//  TEMPLATE FUNCTIONS
template<class T>
    pair<T *, ptrdiff_t> get_temporary_buffer(ptrdiff_t n, T *);
template<class T>
    void return_temporary_buffer(T *p);
template<class InIt, class FwdIt>
    FwdIt uninitialized_copy(InIt first, InIt last, FwdIt result);
template<class FwdIt, class T>
    void uninitialized_fill(FwdIt first, FwdIt last, const T& x);
template<class FwdIt, class Size, class T>
    void uninitialized_fill_n(FwdIt first, Size n, const T& x);
    };

Include the STL standard header <memory> to define a class, an operator, and several templates that help allocate and free objects.


allocator

template<class T>
    class allocator {
    typedef size_t size_type;
    typedef ptrdiff_t difference_type;
    typedef T *pointer;
    typedef const T *const_pointer;
    typedef T& reference;
    typedef const T& const_reference;
    typedef T value_type;
    pointer address(reference x) const;
    const_pointer address(const_reference x) const;
    allocator();
    allocator<T>& operator=(const allocator<T>);
    pointer allocate(size_type n, const void *hint);
    void deallocate(pointer p, size_type n);
    void construct(pointer p, const T& val);
    void destroy(pointer p);
    size_type max_size() const;
    };

The template class describes an object that manages storage allocation and freeing for arrays of objects of type T. An object of class allocator is the default allocator object specified in the constructors for several container template classes in the Standard C++ library.

Template class allocator supplies several type definitions that are rather pedestrian. They hardly seem worth defining. But another class with the same members might choose more interesting alternatives. Constructing a container with an allocator object of such a class gives individual control over allocation and freeing of elements controlled by that container.

For example, an allocator object might allocate storage on a private heap. Or it might allocate storage on a far heap, requiring nonstandard pointers to access the allocated objects. Or it might specify, through the type definitions it supplies, that elements be accessed through special accessor objects that manage shared memory, or perform automatic garbage collection. Hence, a class that allocates storage using an allocator object should always use these types for declaring pointer and reference objects (as do the containers in the Standard C++ library).

Thus, an allocator defines the types (among others):

  • pointer -- behaves like a pointer to T
  • const_pointer -- behaves like a const pointer to T
  • reference -- behaves like a reference to T
  • const_reference -- behaves like a const reference to T

These types specify the form that pointers and references must take for allocated elements. (allocator::types<T>::pointer is not necessarily the same as T * for all allocator objects, even though it has this obvious definition for class allocator.)

In this implementation, if a translator does not support member template functions, it omits the type-mapping member template class:

template<class U>
    struct rebind {
    typedef allocator<U> other;
    };

Thus, how you write an allocator is constrained. A container may need to allocate and free objects other than type T, but cannot use the rebind mechanism to derive a suitable allocator object. This means you cannot write an allocator that uses any pointer or reference types that differ from those used by allocator, and you must supply the member function:

char *_Charalloc(size_type n);

which allocates an object of size n bytes and returns a pointer to its first byte.


allocator::address

pointer address(reference x) const;
const_pointer address(const_reference x) const;

The member functions return the address of x, in the form that pointers must take for allocated elements.


allocator::allocate

pointer allocate(size_type n, const void *hint);

The member function allocates storage for an array of n elements of type T, by calling operator new(n). It returns a pointer to the allocated object. The hint argument helps some allocators in improving locality of reference -- a valid choice is the address of an object earlier allocated by the same allocator object, and not yet deallocated. To supply no hint, use a null pointer argument instead.

In this implementation, if a translator does not support member template functions, the template:

template<class U>
    pointer allocate(size_type n, const U *hint);

is replaced by:

pointer allocate(size_type n, const void *hint);


allocator::allocator

allocator();
allocator(const allocator<T>);

The constructor does nothing. In general, however, an allocator object constructed from another allocator object should compare equal to it (and hence permit intermixing of object allocation and freeing between the two allocator objects).

In this implementation, if a translator does not support member template functions, the template constructor:

template<class U>
    allocator(const allocator<U>);

is replaced by:

allocator(const allocator<T>);

which is the copy constructor.


allocator::const_pointer

typedef const T *pointer;

The pointer type describes an object p that can designate, via the expression *p, any const object that an object of template class allocator can allocate.


allocator::const_reference

typedef const T& const_reference;

The reference type describes an object x that can designate any const object that an object of template class allocator can allocate.


allocator::construct

void construct(pointer p, const T& val);

The member function constructs an object of type T at p by evaluating the placement new expression new ((void *)p) T(val).


allocator::deallocate

void deallocate(pointer p, size_type n);

The member function frees storage for the array of n objects of type T beginning at p, by calling operator delete(p). The pointer p must have been earlier returned by a call to allocate for an allocator object that compares equal to *this, allocating an array object of the same size and type.


allocator::destroy

void destroy(pointer p);

The member function destroys the object designated by p, by calling p->T::~T().


allocator::difference_type

typedef ptrdiff_t difference_type;

The signed integer type describes an object that can represent the difference between the addresses of any two elements in a sequence that an object of template class allocator can allocate.


allocator::max_size

size_type max_size() const;

The member function returns the length of the longest sequence of elements of type T that an object of class allocator might be able to allocate.


allocator::operator=

allocator<T>& operator=(const allocator<T>);

The template assignment operator does nothing. In general, however, an allocator object assigned to another allocator object should compare equal to it (and hence permit intermixing of object allocation and freeing between the two allocator objects).

In this implementation, if a translator does not support member template functions, the template assignment operator:

template<class U>
    allocator<T>& operator=(const allocator<U>);

is replaced by:

allocator<T>& operator=(const allocator<T>);

which is the default assignment operator.


allocator::pointer

typedef T *pointer;

The pointer type describes an object p that can designate, via the expression *p, any object that an object of template class allocator can allocate.


allocator::reference

typedef T& reference;

The reference type describes an object x that can designate any object that an object of template class allocator can allocate.


allocator::size_type

typedef size_t size_type;

The unsigned integer type describes an object that can represent the length of any sequence that an object of template class allocator can allocate.


allocator::value_type

typedef T value_type;

The type is a synonym for the template parameter T.


allocator<void>

class allocator<void> {
    typedef void *pointer;
    typedef const void *const_pointer;
    typedef void value_type;
    allocator();
    template<class U>
        allocator(const allocator<U>);
    template<class U>
        operator=(const allocator<U>);
    };

The class explicitly specializes template class allocator for type void. It defines only the types const_pointer, pointer, and value_type.


auto_ptr

template<class T>
    class auto_ptr {
public:
    typedef T element_type;
    explicit auto_ptr(T *p = 0) throw();
    auto_ptr(const auto_ptr<T>& rhs) throw();
    auto_ptr<T>& operator=(auto_ptr<T>& rhs) throw();
    ~auto_ptr();
    T& operator*() const throw();
    T *operator->() const throw();
    T *get() const throw();
    T *release() const throw();
    };

The class describes an object that stores a pointer to an allocated object of type T. The stored pointer must either be null or designate an object allocated by a new expression. The object also stores an ownership indicator. An object constructed with a non-null pointer owns the pointer. It transfers ownership if its stored value is assigned to another object. The destructor for auto_ptr<T> deletes the allocated object if it owns it. Hence, an object of class auto_ptr<T> ensures that an allocated object is automatically deleted when control leaves a block, even via a thrown exception.


auto_ptr::auto_ptr

explicit auto_ptr(T *p = 0) throw();
auto_ptr(const auto_ptr(auto_ptr<T>& rhs) throw();

The first constructor stores p as the pointer to the allocated object. It stores true as the ownership indicator only if p != 0. The second constructor transfers ownership of the pointer stored in rhs, by storing both the pointer value and the ownership indicator from rhs in the constructed object. It effectively releases the pointer by calling rhs. release ().

In this implementation, if a translator does not support member template functions, the template:

template<class U>
    auto_ptr(const auto_ptr(auto_ptr<U>& rhs) throw();

is replaced by:

auto_ptr(const auto_ptr(auto_ptr<T>& rhs);


auto_ptr::~auto_ptr

~auto_ptr();

If the ownership indicator is true, the destructor deletes the object designated by the stored pointer p by evaluating the delete expression delete p.


auto_ptr::element_type

typedef T element_type;

The type is a synonym for the template parameter T.


auto_ptr::get

T *get() const throw();

The member function returns the stored pointer.


auto_ptr::operator=

auto_ptr<T>& operator=(auto_ptr<>& rhs) throw();

The assignment operator deletes any pointer p that it owns, by evaluating the delete expression delete p. It then transfers ownership of the pointer stored in rhs, by storing both the pointer value and the ownership indicator from rhs in *this. It effectively releases the pointer by calling rhs. release (). The function returns *this.

In this implementation, if a translator does not support member template functions, the template:

template<class U>
    auto_ptr<T>& operator=(auto_ptr<U>& rhs) throw();

is replaced by:

auto_ptr<T>& operator=(auto_ptr<T>& rhs);


auto_ptr::operator*

T& operator*() const throw();

The indirection operator effectively returns * get (). Hence, the stored pointer must not be null.


auto_ptr::operator->

T *operator->() const throw();

The selection operator effectively returns get (), so that the expression al->m behaves the same as (al.get())->m, where al is an object of class auto_ptr<T>. Hence, the stored pointer must not be null, and T must be a class, structure, or union type.


auto_ptr::release

T *release() throw();

The member function sets the ownership indicator to false, then returns the stored pointer.


get_temporary_buffer

template<class T>
    pair<T *, ptrdiff_t> get_temporary_buffer(ptrdiff_t n, T *);

The template function allocates storage for a sequence of at most n elements of type T, from an unspecified source (which may well be the standard heap used by operator new). It returns a value pr, of type pair <T *, ptrdiff_t>. If the function allocates storage, pr. first designates the allocated storage and pr. second is the number of elements in the longest sequence the storage can hold. Otherwise, pr.first is a null pointer.

In this implementation, if a translator does not support member template functions, the template:

template<class T>
    pair<T *, ptrdiff_t> get_temporary_buffer(ptrdiff_t n);

is replaced by:

template<class T>
    pair<T *, ptrdiff_t> get_temporary_buffer(ptrdiff_t n, T *);


operator!=

template<class T>
    bool operator!=(allocator<T>& lhs,
        allocator<T>& rhs);

The template operator returns false.


operator==

template<class T>
    bool operator==(allocator<T>& lhs,
        allocator<T>& rhs);

The template operator returns true. (Two allocator objects should compare equal only if an object allocated through one can be deallocated through the other. If the value of one object is determined from another by assignment or by construction, the two objects should compare equal.)


operator delete

template<class T>
    void operator delete(void *p, size_t n, allocator<T>& al);

The template operator function lets you write a placement delete expression that deallocates storage under control of the allocator object al, as in delete (n, al) p. The function effectively calls al.deallocate(p, n).


operator new

template<class T>
    void *operator new(size_t n, allocator<T>& al);

The template operator function lets you write a placement new expression that allocates storage under control of the allocator object al, as in new(al) U, to allocate and construct a new object of type U. The function effectively returns allocator<T>::rebind<char>::other(al).allocate(n, (void *)0).


raw_storage_iterator

template<class FwdIt, class T>
    class raw_storage_iterator
         : public iterator<output_iterator_tag, void, void> {
public:
    typedef FwdIt iterator_type;
    typedef T element_type;
    explicit raw_storage_iterator(FwdIt it);
    raw_storage_iterator<FwdIt, T>& operator*();
    raw_storage_iterator<FwdIt, T>& operator=(const T& val);
    raw_storage_iterator<FwdIt, T>& operator++();
    raw_storage_iterator<FwdIt, T> operator++(int);
    };

The class describes an output iterator that constructs objects of type T in the sequence it generates. An object of class raw_storage_iterator<FwdIt, T> accesses storage through a forward iterator object, of class FwdIt, that you specify when you construct the object. For an object it of class FwdIt, the expression &*it must designate unconstructed storage for the next object (of type T) in the generated sequence.


raw_storage_iterator::element_type

typedef T element_type;

The type is a synonym for the template parameter T.


raw_storage_iterator::iterator_type

typedef FwdIt iterator_type;

The type is a synonym for the template parameter FwdIt.


raw_storage_iterator::operator*

raw_storage_iterator<FwdIt, T>& operator*();

The indirection operator returns *this (so that operator= (const T&) can perform the actual store in an expression such as *x = val).


raw_storage_iterator::operator=

raw_storage_iterator<FwdIt, T>& operator=(const T& val);

The assignment operator constructs the next object in the output sequence using the stored iterator value it, by evaluating the placement new expression new ((void *)&*it) T(val). The function returns *this.


raw_storage_iterator::operator++

raw_storage_iterator<FwdIt, T>& operator++();
raw_storage_iterator<FwdIt, T> operator++(int);

The first (preincrement) operator increments the stored output iterator object, then returns *this.

The second (postincrement) operator makes a copy of *this, increments the stored output iterator object, then returns the copy.


raw_storage_iterator::raw_storage_iterator

explicit raw_storage_iterator(FwdIt it);

The constructor stores it as the output iterator object.


return_temporary_buffer

template<class T>
    void return_temporary_buffer(T *p);

The template function frees the storage designated by p, which must be earlier allocated by a call to get_temporary_buffer.


uninitialized_copy

template<class InIt, class FwdIt>
    FwdIt uninitialized_copy(InIt first, InIt last, FwdIt result);

The template function effectively executes:

while (first != last)
    new ((void *)&*result++) T(*first++);

where T is the type of *first.


uninitialized_fill

template<class FwdIt, class T>
    void uninitialized_fill(FwdIt first, FwdIt last, const T& x);

The template function effectively executes:

while (first != last)
    new ((void *)&*first++) T(x);


uninitialized_fill_n

template<class FwdIt, class Size, class T>
    void uninitialized_fill_n(FwdIt first, Size n, const T& x);

The template function effectively executes:

while (0 < n--)
    new ((void *)&*first++) T(x);


 <numeric>

<numeric>

namespace std {
template<class InIt, class T>
    T accumulate(InIt first, InIt last, T val);
template<class InIt, class T, class Pred>
    T accumulate(InIt first, InIt last, T val, Pred pr);
template<class InIt1, class InIt2, class T>
    T product(InIt1 first1, InIt1 last1,
        Init2 first2, T val);
template<class InIt1, class InIt2, class T,
    class Pred1, class Pred2>
    T product(InIt1 first1, InIt1 last1,
        Init2 first2, T val, Pred1 pr1, Pred2 pr2);
template<class InIt, class OutIt>
    OutIt partial_sum(InIt first, InIt last,
        OutIt result);
template<class InIt, class OutIt, class Pred>
    OutIt partial_sum(InIt first, InIt last,
        OutIt result, Pred pr);
template<class InIt, class OutIt>
    OutIt adjacent_difference(InIt first, InIt last,
        OutIt result);
template<class InIt, class OutIt, class Pred>
    OutIt adjacent_difference(InIt first, InIt last,
        OutIt result, Pred pr);
    };

Include the STL standard header <numeric> to define several template functions useful for computing numeric values. The descriptions of these templates employ a number of conventions common to all algorithms.


accumulate

template<class InIt, class T>
    T accumulate(InIt first, InIt last, T val);
template<class InIt, class T, class Pred>
    T accumulate(InIt first, InIt last, T val, Pred pr);

The first template function repeatedly replaces val with val + *I, for each value of the InIt iterator I in the interval [first, last). It then returns val.

The second template function repeatedly replaces val with pr(val, *I), for each value of the InIt iterator I in the interval [first, last). It then returns val.

See the related sample program.


adjacent_difference

template<class InIt, class OutIt>
    OutIt adjacent_difference(InIt first, InIt last,
        OutIt result);
template<class InIt, class OutIt, class Pred>
    OutIt adjacent_difference(InIt first, InIt last,
        OutIt result, Pred pr);

The first template function stores successive values beginning at result, for each value of the InIt iterator I in the interval [first, last). The first value val stored (if any) is *I. Each subsequent value stored is *I - val, and val is replaced by *I. The function returns result incremented last - first times.

The second template function stores successive values beginning at result, for each value of the InIt iterator I in the interval [first, last). The first value val stored (if any) is *I. Each subsequent value stored is pr(*I, val), and val is replaced by *I. The function returns result incremented last - first times.

See the related sample program.


inner_product

template<class InIt1, class InIt2, class T>
    T product(InIt1 first1, InIt1 last1,
        Init2 first2, T val);
template<class InIt1, class InIt2, class T,
    class Pred1, class Pred2>
    T product(InIt1 first1, InIt1 last1,
        Init2 first2, T val, Pred1 pr1, Pred2 pr2);

The first template function repeatedly replaces val with val + (*I1 * *I2), for each value of the InIt1 iterator I1 in the interval [first1, last2). In each case, the InIt2 iterator I2 equals first2 + (I1 - first1). The function returns val.

The second template function repeatedly replaces val with pr1(val, pr2(*I1, *I2)), for each value of the InIt1 iterator I1 in the interval [first1, last2). In each case, the InIt2 iterator I2 equals first2 + (I1 - first1). The function returns val.

See the related sample program.


partial_sum

template<class InIt, class OutIt>
    OutIt partial_sum(InIt first, InIt last,
        OutIt result);
template<class InIt, class OutIt, class Pred>
    OutIt partial_sum(InIt first, InIt last,
        OutIt result, Pred pr);

The first template function stores successive values beginning at result, for each value of the InIt iterator I in the interval [first, last). The first value val stored (if any) is *I. Each subsequent value val stored is val + *I. The function returns result incremented last - first times.

The second template function stores successive values beginning at result, for each value of the InIt iterator I in the interval [first, last). The first value val stored (if any) is *I. Each subsequent value val stored is pr(val, *I). The function returns result incremented last - first times.

See the related sample program.


 <ostream>

<ostream>

namespace std {
    template<class E, class T = char_traits<E> >
        class basic_ostream;
    typedef basic_ostream<char, char_traits<char> > ostream;
    typedef basic_ostream<wchar_t, char_traits<wchar_t> > wostream;
//      INSERTERS
    template<class E, class T>
        basic_ostream<E, T>& operator<<(basic_ostream<E, T> os, const E *s);
    template<class E, class T>
        basic_ostream<E, T>& operator<<(basic_ostream<E, T> os, E c);
    template<class T>
        basic_ostream<char, T>& operator<<(basic_ostream<char, T> os, const signed char *s);
    template<class T>
        basic_ostream<char, T>& operator<<(basic_ostream<char, T> os, signed char c);
    template<class T>
        basic_ostream<char, T>& operator<<(basic_ostream<char, T> os, const unsigned char *s);
    template<class T>
        basic_ostream<char, T>& operator<<(basic_ostream<char, T> os, unsigned char c);
//      MANIPULATORS
    template class<E, T>
        basic_ostream<E, T>& endl(basic_ostream<E, T> os);
    template class<E, T>
        basic_ostream<E, T>& ends(basic_ostream<E, T> os);
    template class<E, T>
        basic_ostream<E, T>& flush(basic_ostream<E, T> os);
    };

Include the iostreams standard header <ostream> to define template class basic_ostream, which mediates extractions for the iostreams classes. The header also defines several related manipulators. (This header is typically included for you by another of the iostreams headers. You seldom have occasion to include it directly.)


basic_ostream

basic_ostream · flush · operator<< · opfx · osfx · put · seekp · sentry · tellp · write

template <class E, class T = char_traits<E> >
    class basic_ostream {
public:
    class sentry;
    explicit basic_ostream(basic_streambuf<E, T> *sb);
    virtual ~ostream();
    bool opfx();
    void osfx();
    basic_ostream& operator<<(basic_ostream& (*pf)(basic_ostream&));
    basic_ostream& operator<<(basic_ios<E, T>& (*pf)(basic_ios<E, T>&));
    basic_ostream& operator<<(ios_base<E, T>& (*pf)(ios_base<E, T>&));
    basic_ostream& operator<<(basic_streambuf<E, T> *sb);
    basic_ostream& operator<<(const char *s);
    basic_ostream& operator<<(char c);
    basic_ostream& operator<<(bool n);
    basic_ostream& operator<<(short n);
    basic_ostream& operator<<(unsigned short n);
    basic_ostream& operator<<(int n);
    basic_ostream& operator<<(unsigned int n);
    basic_ostream& operator<<(long n);
    basic_ostream& operator<<(unsigned long n);
    basic_ostream& operator<<(float n);
    basic_ostream& operator<<(double n);
    basic_ostream& operator<<(long double n);
    basic_ostream& operator<<(void * n);
    basic_ostream& put(E c);
    basic_ostream& write(E *s, streamsize n);
    basic_ostream& flush();
    pos_type tellp();
    basic_ostream& seekp(pos_type pos);
    basic_ostream& seekp(off_type off, ios_base::seek_dir way);
    };

The template class describes an object that controls insertion of elements and encoded objects into a stream buffer with elements of type E, whose character traits are determined by the class T.

Most of the member functions that overload operator<< are formatted output functions. They follow the pattern:

    iostate state = goodbit;
    const sentry ok(*this);
    if (ok)
        {try
            {convert and insert elements
            accumulate flags in state}
        catch (...)
            {if (exceptions() & badbit)
                throw;
            setstate(badbit); }}
    width(0);    // except for operator<<(E)
    setstate(state);
    return (*this);

Two other member functions are unformatted output functions. They follow the pattern:

    iostate state = goodbit;
    const sentry ok(*this);
    if (!ok)
        state |= badbit;
    else
        {try
            {obtain and insert elements
            accumulate flags in state}
        catch (...)
            {if (rdstate() & badbit)
                throw;
            setstate(badbit); }}
    setstate(state);
    return (*this);

Both groups of functions call setstate (badbit) if they encounter a failure while inserting elements.

An object of class basic_ostream<E, T> stores only a virtual public base object of class basic_ios <E, T>.


basic_ostream::basic_ostream

explicit basic_ostream(basic_streambuf<E, T> *sb);

The constructor initializes the base class by calling init (sb).


basic_ostream::flush

basic_ostream& flush();

If rdbuf () is not a null pointer, the function calls rdbuf()-> pubsync (). If that returns -1, the function calls setstate (badbit). It returns *this.


basic_ostream::operator<<

basic_ostream& operator<<(
    basic_ostream& (*pf)(basic_ostream&));
basic_ostream& operator<<(
    basic_ios<E, T>& (*pf)(basic_ios<E, T>&));
basic_ostream& operator<<(
    ios_base<E, T>& (*pf)(ios_base<E, T>&));
basic_ostream& operator<<(
    basic_streambuf<E, T> *sb);
basic_ostream& operator<<(const char *s);
basic_ostream& operator<<(char c);
basic_ostream& operator<<(bool n);
basic_ostream& operator<<(short n);
basic_ostream& operator<<(unsigned short n);
basic_ostream& operator<<(int n);
basic_ostream& operator<<(unsigned int n);
basic_ostream& operator<<(long n);
basic_ostream& operator<<(unsigned long n);
basic_ostream& operator<<(float n);
basic_ostream& operator<<(double n);
basic_ostream& operator<<(long double n);
basic_ostream& operator<<(void *n);

The first member function ensures that an expression of the form ostr <<: endl calls endl (ostr), then returns *this. The second and third functions ensure that other manipulators, such as hex behave similarly. The remaining functions are all formatted output functions.

The function:

basic_ostream& operator<<(
    basic_streambuf<E, T> *sb);

extracts elements from sb, if sb is not a null pointer, and inserts them. Extraction stops on end-of-file, or if an extraction throws an exception (which is rethrown). It also stops, without extracting the element in question, if an insertion fails. If the function inserts no elements, or if an extraction throws an exception, the function calls setstate (failbit). In any case, the function returns *this.

The function:

basic_ostream& operator<<(const char *s);

determines the length n = strlen(s) of the sequence beginning at s, and inserts the widened sequence. Each element c of the sequence is widened by calling use_facet < ctype <E> >( getloc ()). widen (c). If n < width (), then the function also inserts a repetition of width() - n fill characters. The repetition precedes the sequence if ( flags () & adjustfield != left. Otherwise, the repetition follows the sequence.

The function:

basic_ostream& operator<<(char c);

inserts the widened element use_facet < ctype <E> >( getloc ()). widen (c). It returns *this.

The function:

basic_ostream& operator<<(bool n);

converts n to a Boolean field and inserts it by calling use_facet <num_put<E, OutIt>( getloc ()). put (OutIt( rdbuf ()), *this, getloc(), n). Here, OutIt is defined as ostreambuf_iterator <E, T>. The function returns *this.

The functions:

basic_ostream& operator<<(short n);
basic_ostream& operator<<(unsigned short n);
basic_ostream& operator<<(int n);
basic_ostream& operator<<(unsigned int n);
basic_ostream& operator<<(long n);
basic_ostream& operator<<(unsigned long n);
basic_ostream& operator<<(void *n);

each convert n to a numeric field and insert it by calling use_facet <num_put<E, OutIt>( getloc ()). put (OutIt( rdbuf ()), *this, getloc(), n). Here, OutIt is defined as ostreambuf_iterator <E, T>. The function returns *this.

The functions:

basic_ostream& operator<<(float n);
basic_ostream& operator<<(double n);
basic_ostream& operator<<(long double n);

each convert n to a numeric field and insert it by calling use_facet <num_put<E, OutIt>( getloc ()). put (OutIt( rdbuf ()), *this, getloc(), n). Here, OutIt is defined as ostreambuf_iterator <E, T>. The function returns *this.


basic_ostream::opfx

bool opfx();

If good () is true, and tie () is not a null pointer, the member function calls tie-> flush (). It returns good().

You should not call opfx directly. It is called as needed by an object of class sentry.


basic_ostream::osfx

void osfx();

If flags () & unitbuf is nonzero, the member function calls flush (). You should not call osfx directly. It is called as needed by an object of class sentry.


basic_ostream::put

basic_ostream& put(E c);

The unformatted output function inserts the element c. It returns *this.


basic_ostream::seekp

basic_ostream& seekp(pos_type pos);
basic_ostream& seekp(off_type off, ios_base::seek_dir way);

If fail () is false, the first member function calls rdbuf ()-> pubseekpos (pos). If fail() is false, the second function calls rdbuf()-> pubseekoff (off, way). Both functions return *this.


basic_ostream::sentry

class sentry {
public:
    explicit sentry(basic_ostream<E, T>& os);
    operator bool() const;
    };

The nested class describes an object whose declaration structures the formatted output functions and the unformatted output functions. The constructor effectively calls os. opfx () and stores the return value. operator bool() delivers this return value. The destructor effectively calls os. osfx (), but only if uncaught_exception () returns false.


basic_ostream::tellp

pos_type tellp();

If fail () is false, the member function returns rdbuf ()-> pubseekoff (0, cur , in ). Otherwise, it returns streampos(-1).


basic_ostream::write

basic_ostream& write(const E *s, streamsize n);

The unformatted output function inserts the sequence of n elements beginning at s.


endl

template class<E, T>
    basic_ostream<E, T>& endl(basic_ostream<E, T> os);

The manipulator calls os. put (os. widen ('\n')), then calls os. flush (). It returns os.


ends

template class<E, T>
    basic_ostream<E, T>& ends(basic_ostream<E, T> os);

The manipulator calls os. put (E('\0')). It returns os.


flush

template class<E, T>
    basic_ostream<E, T>& flush(basic_ostream<E, T> os);

The manipulator calls os. flush (). It returns os.


operator<<

template<class E, class T>
    basic_ostream<E, T>& operator<<(basic_ostream<E, T> os, const E *s);
template<class E, class T>
    basic_ostream<E, T>& operator<<(basic_ostream<E, T> os, E c);
template<class T>
    basic_ostream<char, T>& operator<<(basic_ostream<char, T> os, const signed char *s);
template<class T>
   basic_ostream<char, T>& operator<<(basic_ostream<char, T> os, signed char c);
template<class T>
    basic_ostream<char, T>& operator<<(basic_ostream<char, T> os, const unsigned char *s);
template<class T>
   basic_ostream<char, T>& operator<<(basic_ostream<char, T> os, unsigned char c);

The template function:

template<class E, class T>
    basic_ostream<E, T>& operator<<(basic_ostream<E, T> os, const E *s);

determines the length n = T:: length (s) of the sequence beginning at s, and inserts the sequence. If n < os. width (), then the function also inserts a repetition of width() - n fill characters. The repetition precedes the sequence if (os. flags () & adjustfield != left. Otherwise, the repetition follows the sequence. The function returns os.

The template function:

template<class E, class T>
    basic_ostream<E, T>& operator<<(basic_ostream<E, T> os, E c);

is a formatted output function that inserts the element c. It returns os.

The template function:

template<class T>
    basic_ostream<char, T>& operator<<(basic_ostream<char, T> os, const signed char *s);

returns os << (const char *)s.

The template function:

template<class T>
    basic_ostream<char, T>& operator<<(basic_ostream<char, T> os, signed char c);

returns os << (char)c.

The template function:

template<class T>
    basic_ostream<char, T>& operator<<(basic_ostream<char, T> os, const unsigned char *s);

returns os << (const char *)s.

The template function:

template<class T>
    basic_ostream<char, T>& operator<<(basic_ostream<char, T> os, unsigned char c);

returns os << (char)c.


ostream

typedef basic_ostream<char, char_traits<char> > ostream;

The type is a synonym for template class basic_ostream, specialized for elements of type char with default character traits.


wostream

typedef basic_ostream<wchar_t, char_traits<wchar_t> > wostream;

The type is a synonym for template class basic_ostream, specialized for elements of type wchar_t with default character traits.


 <queue>

<queue>

namespace std {
template<class T, class Cont>
    class queue;
template<class T, class Cont, class Pred>
    class priority_queue;
//    TEMPLATE FUNCTIONS
template<class T, class Cont>
    bool operator==(const queue<T, Cont>& lhs,
        const queue<T, Cont>&);
template<class T, class Cont>
    bool operator!=(const queue<T, Cont>& lhs,
        const queue<T, Cont>&);
template<class T, class Cont>
    bool operator<(const queue<T, Cont>& lhs,
        const queue<T, Cont>&);
template<class T, class Cont>
    bool operator>(const queue<T, Cont>& lhs,
        const queue<T, Cont>&);
template<class T, class Cont>
    bool operator<=(const queue<T, Cont>& lhs,
        const queue<T, Cont>&);
template<class T, class Cont>
    bool operator>=(const queue<T, Cont>& lhs,
        const queue<T, Cont>&);
    };

Include the STL standard header <queue> to define the template classes priority_queue and queue, and two supporting templates.


operator!=

template<class T, class Cont>
    bool operator!=(const queue <T, Cont>& lhs,
        const queue <T, Cont>& rhs);

The template function returns !(lhs == rhs).


operator==

template<class T, class Cont>
    bool operator==(const queue <T, Cont>& lhs,
        const queue <T, Cont>& rhs);

The template function overloads operator== to compare two objects of template class queue. The function returns lhs. c == rhs.c.


operator<

template<class T, class Cont>
    bool operator<(const queue <T, Cont>& lhs,
        const queue <T, Cont>& rhs);

The template function overloads operator< to compare two objects of template class queue. The function returns lhs. c < rhs.c.


operator<=

template<class T, class Cont>
    bool operator<=(const queue <T, Cont>& lhs,
        const queue <T, Cont>& rhs);

The template function returns !(rhs < lhs).


operator>

template<class T, class Cont>
    bool operator>(const queue <T, Cont>& lhs,
        const queue <T, Cont>& rhs);

The template function returns rhs < lhs.


operator>=

template<class T, class Cont>
    bool operator>=(const queue <T, Cont>& lhs,
        const queue <T, Cont>& rhs);

The template function returns !(lhs < rhs).


priority_queue

template<class T,
    class Cont = vector<T>,
    class Pred = less<Cont::value_type> >
    class priority_queue {
public:
    typedef Cont::allocator_type allocator_type;
    typedef Cont::value_type value_type;
    typedef Cont::size_type size_type;
    explicit priority_queue(const Pred& pr = Pred(),
        const allocator_type& al = allocator_type());
    priority_queue(const value_type *first, const value_type *last,
        const Pred& pr = Pred(), const allocator_type& al = allocator_type());
    bool empty() const;
    size_type size() const;
    allocator_type get_allocator() const;
    value_type& top();
    const value_type& top() const;
    void push(const value_type& x);
    void pop();
protected:
    Cont c;
    Pred comp;
    };

The template class describes an object that controls a varying-length sequence of elements. The object allocates and frees storage for the sequence it controls through a protected object named c, of class Cont. The type T of elements in the controlled sequence must match value_type.

The sequence is ordered using a protected object named comp. After each insertion or removal of the top element (at position zero), for the iterators P0 and Pi designating elements at positions 0 and i, comp(*P0, *Pi) is false. (For the default template parameter less <Cont::value_type>, the top element of the sequence compares largest, or highest priority.)

An object of class Cont must supply random-access iterators and several public members defined the same as for deque and vector (both of which are suitable candidates for class Cont). The required members are:

    typedef T value_type;
    typedef T0 size_type;
    Cont(const A& al);
    Cont(InIt first, InIt last, const allocator_type& al);
    bool empty() const;
    size_type size() const;
    allocator_type get_allocator() const;
    const value_type& front() const;
    value_type& front();
    void push_back(const value_type& x);
    void pop_back();

Here, T0 is an unspecified type that meets the stated requirements.


priority_queue::allocator_type

typedef Cont::allocator_type allocator_type;

The type is a synonym for Cont::allocator_type.


priority_queue::empty

bool empty() const;

The member function returns true for an empty controlled sequence.

See the related sample program.


priority_queue::get_allocator

allocator_type get_allocator() const;

The member function returns c.get_allocator().


priority_queue::pop

void pop();

The member function removes the first element of the controlled sequence, which must be non-empty, then reorders it.

See the related sample program.


priority_queue::priority_queue

explicit priority_queue(const Pred& pr = Pred(),
    const allocator_type& al = allocator_type());
priority_queue(const value_type *first, const value_type *last,
    const Pred& pr = Pred(), const allocator_type& al = allocator_type());

Both constructors store pr in comp and effectively initialize the stored object with c (al), to specify an empty initial controlled sequence. The template constructor then calls push (x) for x, an iterator of class InIt in the range [first, last).

In this implementation, if a translator does not support member template functions, the template:

template<class InIt>
    priority_queue(InIt first, InIt last,
        const Pred& pr = Pred(), const allocator_type& al = allocator_type());

is replaced by:

priority_queue(const value_type *first, const value_type *last,
    const Pred& pr = Pred(), const allocator_type& al = allocator_type());


priority_queue::push

void push(const T& x);

The member function inserts an element with value x at the end of the controlled sequence, then reorders it.

See the related sample program.


priority_queue::size

size_type size() const;

The member function returns the length of the controlled sequence.

See the related sample program.


priority_queue::size_type

typedef Cont::size_type size_type;

The type is a synonym for Cont::size_type.


priority_queue::top

value_type& top();
const value_type& top() const;

The member function returns a reference to the first (highest priority) element of the controlled sequence, which must be non-empty.

See the related sample program.


priority_queue::value_type

typedef Cont::value_type value_type;

The type is a synonym for Cont::value_type.


queue

template<class T,
    class Cont = deque<T> >
    class queue {
public:
    typedef Cont::allocator_type allocator_type;
    typedef Cont::value_type value_type;
    typedef Cont::size_type size_type;
    explicit queue(const allocator_type& al = allocator_type()) const;
    bool empty() const;
    size_type size() const;
    allocator_type get_allocator() const;
    value_type& top();
    const value_type& top() const;
    void push(const value_type& x);
    void pop();
protected:
    Cont c;
    };

The template class describes an object that controls a varying-length sequence of elements. The object allocates and frees storage for the sequence it controls through a protected object named c, of class Cont. The type T of elements in the controlled sequence must match value_type.

An object of class Cont must supply several public members defined the same as for deque and list (both of which are suitable candidates for class Cont). The required members are:

    typedef T value_type;
    typedef T0 size_type;
    Cont(const allocator_type& al);
    bool empty() const;
    size_type size() const;
    allocator_type get_allocator() const;
    value_type& front();
    const value_type& front() const;
    value_type& back();
    const value_type& back() const;
    void push_back(const value_type& x);
    void pop_front();

Here, T0 is an unspecified type that meets the stated requirements.


queue::allocator_type

typedef Cont::allocator_type allocator_type;

The type is a synonym for Cont::allocator_type.


queue::back

value_type& back();
const value_type& back() const;

The member function returns a reference to the last element of the controlled sequence, which must be non-empty.

See the related sample program.


queue::empty

bool empty() const;

The member function returns true for an empty controlled sequence.

See the related sample program.


queue::front

value_type& front();
const value_type& front() const;

The member function returns a reference to the first element of the controlled sequence, which must be non-empty.

See the related sample program.


queue::get_allocator

allocator_type get_allocator() const;

The member function returns c.get_allocator().


queue::pop

void pop();

The member function removes the last element of the controlled sequence, which must be non-empty.

See the related sample program.


queue::push

void push(const T& x);

The member function inserts an element with value x at the end of the controlled sequence.

See the related sample program.


queue::queue

explicit queue(const allocator_type& al = allocator_type());

The constructor initializes the stored object with c (al), to specify an empty initial controlled sequence.


queue::size

size_type size() const;

The member function returns the length of the controlled sequence.


queue::size_type

typedef Cont::size_type size_type;

The type is a synonym for Cont::size_type.


queue::top

value_type& top();
const value_type& top() const;

The member function returns a reference to the first element of the controlled sequence, which must be non-empty.


queue::value_type

typedef Cont::value_type value_type;

The type is a synonym for Cont::value_type.


 <set>

<set>

namespace std {
template<class Key, class Pred, class A>
    class set;
template<class Key, class Pred, class A>
    class multiset;
//    TEMPLATE FUNCTIONS
template<class Key, class Pred, class A>
    bool operator==(
        const set<Key, Pred, A>& lhs,
        const set<Key, Pred, A>& rhs);
template<class Key, class Pred, class A>
    bool operator==(
        const multiset<Key, Pred, A>& lhs,
        const multiset<Key, Pred, A>& rhs);
template<class Key, class Pred, class A>
    bool operator!=(
        const set<Key, Pred, A>& lhs,
        const set<Key, Pred, A>& rhs);
template<class Key, class Pred, class A>
    bool operator!=(
        const multiset<Key, Pred, A>& lhs,
        const multiset<Key, Pred, A>& rhs);
template<class Key, class Pred, class A>
    bool operator<(
        const set<Key, Pred, A>& lhs,
        const set<Key, Pred, A>& rhs);
template<class Key, class Pred, class A>
    bool operator<(
        const multiset<Key, Pred, A>& lhs,
        const multiset<Key, Pred, A>& rhs);
template<class Key, class Pred, class A>
    bool operator>(
        const set<Key, Pred, A>& lhs,
        const set<Key, Pred, A>& rhs);
template<class Key, class Pred, class A>
    bool operator>(
        const multiset<Key, Pred, A>& lhs,
        const multiset<Key, Pred, A>& rhs);
template<class Key, class Pred, class A>
    bool operator<=(
        const set<Key, Pred, A>& lhs,
        const set<Key, Pred, A>& rhs);
template<class Key, class Pred, class A>
    bool operator<=(
        const multiset<Key, Pred, A>& lhs,
        const multiset<Key, Pred, A>& rhs);
template<class Key, class Pred, class A>
    bool operator>=(
        const set<Key, Pred, A>& lhs,
        const set<Key, Pred, A>& rhs);
template<class Key, class Pred, class A>
    bool operator>=(
        const multiset<Key, Pred, A>& lhs,
        const multiset<Key, Pred, A>& rhs);
template<class Key, class Pred, class A>
    void swap(
        const set<Key, Pred, A>& lhs,
        const set<Key, Pred, A>& rhs);
template<class Key, class Pred, class A>
    void swap(
        const multiset<Key, Pred, A>& lhs,
        const multiset<Key, Pred, A>& rhs);
    };

Include the STL standard header <set> to define the container template classes set and multiset, and their supporting templates.


multiset

allocator_type · begin · clear · const_iterator · const_reference · const_reverse_iterator · count · difference_type · empty · end · equal_range · erase · find · get_allocator · insert · iterator · key_comp · key_compare · key_type · lower_bound · max_size · multiset · rbegin · reference · rend · reverse_iterator · size · size_type · swap · upper_bound · value_comp · value_compare · value_type

template<class Key, class Pred = less<Key>, class A = allocator<Key> >
    class multiset {
public:
    typedef Key key_type;
    typedef Pred key_compare;
    typedef Key value_type;
    typedef Pred value_compare;
    typedef A allocator_type;
    typedef A::size_type size_type;
    typedef A::difference_type difference_type;
    typedef A::rebind<value_type>::other::const_reference reference;
    typedef A::rebind<value_type>::other::const_reference const_reference;
    typedef T0 iterator;
    typedef T1 const_iterator;
    typedef reverse_bidirectional_iterator<iterator,
        value_type, reference, A::const_pointer,
            difference_type> reverse_iterator;
    typedef reverse_bidirectional_iterator<const_iterator,
        value_type, const_reference, A::pointer,
            difference_type> const_reverse_iterator;
    explicit multiset(const Pred& comp = Pred(), const A& al = A());
    multiset(const multiset& x);
    multiset(const value_type *first, const value_type *last,
        const Pred& comp = Pred(), const A& al = A());
    const_iterator begin() const;
    iterator end() const;
    const_reverse_iterator rbegin() const;
    const_reverse_iterator rend() const;
    size_type size() const;
    size_type max_size() const;
    bool empty() const;
    A get_allocator() const;
    iterator insert(const value_type& x);
    iterator insert(iterator it, const value_type& x);
    void insert(const value_type *first, const value_type *last);
    iterator erase(iterator it);
    iterator erase(iterator first, iterator last);
    size_type erase(const Key& key);
    void clear();
    void swap(multiset x);
    key_compare key_comp() const;
    value_compare value_comp() const;
    const_iterator find(const Key& key) const;
    size_type count(const Key& key) const;
    const_iterator lower_bound(const Key& key) const;
    const_iterator upper_bound(const Key& key) const;
    pair<const_iterator, const_iterator>
        equal_range(const Key& key) const;
protected:
    A allocator;
    };

The template class describes an object that controls a varying-length sequence of elements of type const Key. Each element serves as both a sort key and a value. The sequence is represented in a way that permits lookup, insertion, and removal of an arbitrary element with a number of operations proportional to the logarithm of the number of elements in the sequence (logarithmic time). Moreover, inserting an element invalidates no iterators, and removing an element invalidates only those iterators that point at the removed element.

The object orders the sequence it controls by calling a stored function object of type Pred. You access this stored object by calling the member function key_comp (). Such a function object must impose a total order on sort keys. For any element x that precedes y in the sequence, key_comp()(y, x) is false. (For the default function object less <Key>, sort keys never decrease in value.) Unlike template class set, an object of template class multiset does not ensure that key_comp()(x, y) is true. (Keys need not be unique.)

The object allocates and frees storage for the sequence it controls through a protected object named allocator, of class A. Such an allocator object must have the same external interface as an object of template class allocator. Note that allocator is not copied when the object is assigned.


multiset::allocator_type

yypedef A allocator_type;

The type is a synonym for the template parameter A.


multiset::begin

const_iterator begin() const;

The member function returns a bidirectional iterator that points at the first element of the sequence (or just beyond the end of an empty sequence).


multiset::clear

void clear() const;

The member function calls erase ( begin (), end ()).


multiset::const_iterator

typedef T1 const_iterator;

The type describes an object that can serve as a constant bidirectional iterator for the controlled sequence. It is described here as a synonym for the unspecified type T1.


multiset::const_reference

typedef A::rebind<value_type>::other::const_reference const_reference;

The type describes an object that can serve as a constant reference to an element of the controlled sequence.


multiset::const_reverse_iterator

typedef reverse_bidirectional_iterator<const_iterator,
    value_type, const_reference, A::const_pointer,
        difference_type> const_reverse_iterator;

The type describes an object that can serve as a constant reverse bidirectional iterator for the controlled sequence.


multiset::count

size_type count(const Key& key) const;

The member function returns the number of elements x in the range [ lower_bound (key), upper_bound (key)).


multiset::difference_type

typedef A::difference_type difference_type;

The signed integer type describes an object that can represent the difference between the addresses of any two elements in the controlled sequence.


multiset::empty

bool empty() const;

The member function returns true for an empty controlled sequence.


multiset::end

const_iterator end() const;

The member function returns a bidirectional iterator that points just beyond the end of the sequence.


multiset::equal_range

pair<const_iterator, const_iterator>
    equal_range(const Key& key) const;

The member function returns a pair of iterators x such that x.first == lower_bound (key) and x.second == upper_bound (key).


multiset::erase

iterator erase(iterator it);
iterator erase(iterator first, iterator last);
size_type erase(const Key& key);

The first member function removes the element of the controlled sequence pointed to by it. The second member function removes the elements in the range [first, last). Both return an iterator that designates the first element remaining beyond any elements removed, or end () if no such element exists.

The third member removes the elements with sort keys in the range [ lower_bound (key), upper_bound (key)). It returns the number of elements it removes.


multiset::find

const_iterator find(const Key& key) const;

The member function returns an iterator that designates the earliest element in the controlled sequence whose sort key equals key. If no such element exists, the iterator equals end ().


multiset::get_allocator

A get_allocator() const;

The member function returns allocator.


multiset::insert

iterator insert(const value_type& x);
iterator insert(iterator it, const value_type& x);
void insert(const value_type *first, const value_type *last);

The first member function inserts the element x in the controlled sequence, then returns the iterator that designates the inserted element. The second member function returns insert(x), using it as a starting place within the controlled sequence to search for the insertion point. (Insertion can occur in amortized constant time, instead of logarithmic time, if the insertion point immediately follows it.) The third member function inserts the sequence of element values in the range [first, last).

In this implementation, if a translator does not support member template functions, the template:

template<class InIt>
    void insert(InIt first, InIt last);

is replaced by:

void insert(const value_type *first, const value_type *last);


multiset::iterator

typedef T0 iterator;

The type describes an object that can serve as a bidirectional iterator for the controlled sequence. It is described here as a synonym for the unspecified type T0.


multiset::key_comp

key_compare key_comp() const;

The member function returns the stored function object that determines the order of elements in the controlled sequence. The stored object defines the member function:

bool operator(const Key& x, const Key& y);

which returns true if x strictly precedes y in the sort order.


multiset::key_compare

typedef Pred key_compare;

The type describes a function object that can compare two sort keys to determine the relative order of any two elements in the controlled sequence.


multiset::key_type

typedef Key key_type;

The type describes the sort key object that constitutes each element of the controlled sequence.


multiset::lower_bound

const_iterator lower_bound(const Key& key) const;

The member function returns an iterator that designates the earliest element x in the controlled sequence for which key_comp ()(x, key) is false.

If no such element exists, the function returns end ().


multiset::max_size

size_type max_size() const;

The member function returns the length of the longest sequence that the object can control.


multiset::multiset

explicit multiset(const Pred& comp = Pred(), const A& al = A());
multiset(const multiset& x);
multiset(const value_type *first, const value_type *last,
    const Pred& comp = Pred(), const A& al = A());

The constructors with an argument named comp store the function object so that it can be later returned by calling key_comp (). All constructors also store the allocator object al (or, for the copy constructor, x. get_allocator ()) in allocator and initialize the controlled sequence. The first constructor specifies an empty initial controlled sequence. The second constructor specifies a copy of the sequence controlled by x. The last constructor specifies the sequence of element values [first, last).

In this implementation, if a translator does not support member template functions, the template:

template<class InIt>
    multiset(InIt first, InIt last,
        const Pred& comp = Pred(), const A& al = A());

is replaced by:

multiset(const value_type *first, const value_type *last,
    const Pred& comp = Pred(), const A& al = A());


multiset::rbegin

const_reverse_iterator rbegin() const;

The member function returns a reverse bidirectional iterator that points just beyond the end of the controlled sequence. Hence, it designates the beginning of the reverse sequence.


multiset::reference

typedef A::rebind<value_type>::other::const_reference reference;

The type describes an object that can serve as a reference to an element of the controlled sequence.


multiset::rend

const_reverse_iterator rend() const;

The member function returns a reverse bidirectional iterator that points at the first element of the sequence (or just beyond the end of an empty sequence). Hence, it designates the end of the reverse sequence.


multiset::reverse_iterator

typedef reverse_bidirectional_iterator<iterator,
    value_type, reference, A::pointer,
        difference_type> reverse_iterator;

The type describes an object that can serve as a reverse bidirectional iterator for the controlled sequence.


multiset::size

size_type size() const;

The member function returns the length of the controlled sequence.


multiset::size_type

typedef A::size_type size_type;

The unsigned integer type describes an object that can represent the length of any controlled sequence.


multiset::swap

void swap(multiset& str);

The member function swaps the controlled sequences between *this and str. If allocator == str.allocator, it does so in constant time. Otherwise, it performs a number of element assignments and constructor calls proportional to the number of elements in the two controlled sequences.


multiset::upper_bound

const_iterator upper_bound(const Key& key) const;

The member function returns an iterator that designates the earliest element x in the controlled sequence for which key_comp ()(key, x) is true.

If no such element exists, the function returns end ().


multiset::value_comp

value_compare value_comp() const;

The member function returns a function object that determines the order of elements in the controlled sequence.


multiset::value_compare

typedef Pred value_compare;

The type describes a function object that can compare two elements as sort keys to determine their relative order in the controlled sequence.


multiset::value_type

typedef Key value_type;

The type describes an element of the controlled sequence.


operator!=

template<class Key, class Pred, class A>
    bool operator!=(
        const set <Key, Pred, A>& lhs,
        const set <Key, Pred, A>& rhs);
template<class Key, class Pred, class A>
    bool operator!=(
        const multiset <Key, Pred, A>& lhs,
        const multiset <Key, Pred, A>& rhs);

The template function returns !(lhs == rhs).


operator==

template<class Key, class Pred, class A>
    bool operator==(
        const set <Key, Pred, A>& lhs,
        const set <Key, Pred, A>& rhs);
template<class Key, class Pred, class A>
    bool operator==(
        const multiset <Key, Pred, A>& lhs,
        const multiset <Key, Pred, A>& rhs);

The first template function overloads operator== to compare two objects of template class set. The second template function overloads operator== to compare two objects of template class multiset. Both functions return lhs. size () == rhs.size() && equal (lhs. begin (), lhs. end (), rhs.begin()).


operator<

template<class Key, class Pred, class A>
    bool operator<(
        const set <Key, Pred, A>& lhs,
        const set <Key, Pred, A>& rhs);
template<class Key, class Pred, class A>
    bool operator<(
        const multiset <Key, Pred, A>& lhs,
        const multiset <Key, Pred, A>& rhs);

The first template function overloads operator< to compare two objects of template class set. The second template function overloads operator< to compare two objects of template class multiset. Both functions return lexicographical_compare (lhs. begin (), lhs. end (), rhs.begin(), rhs.end()).


operator<=

template<class Key, class Pred, class A>
    bool operator<=(
        const set <Key, Pred, A>& lhs,
        const set <Key, Pred, A>& rhs);
template<class Key, class Pred, class A>
    bool operator<=(
        const multiset <Key, Pred, A>& lhs,
        const multiset <Key, Pred, A>& rhs);

The template function returns !(rhs < lhs).


operator>

template<class Key, class Pred, class A>
    bool operator>(
        const set <Key, Pred, A>& lhs,
        const set <Key, Pred, A>& rhs);
template<class Key, class Pred, class A>
    bool operator>(
        const multiset <Key, Pred, A>& lhs,
        const multiset <Key, Pred, A>& rhs);

The template function returns rhs < lhs.


operator>=

template<class Key, class Pred, class A>
    bool operator>=(
        const set <Key, Pred, A>& lhs,
        const set <Key, Pred, A>& rhs);
template<class Key, class Pred, class A>
    bool operator>=(
        const multiset <Key, Pred, A>& lhs,
        const multiset <Key, Pred, A>& rhs);

The template function returns !(lhs < rhs).


set

allocator_type · begin · clear · const_iterator · < b>const_reference · const_reverse_iterator · count · difference_type · empty · end · equal_range · erase · find · get_allocator · insert · iterator · key_comp · key_compare · key_type · lower_bound · set · max_size · rbegin · reference · rend · reverse_iterator · size · size_type · swap · upper_bound · value_comp · value_ compare · value_type

template<class Key, class Pred = less<Key>, class A = allocator<Key> >
    class set {
public:
    typedef Key key_type;
    typedef Pred key_compare;
    typedef Key value_type;
    typedef Pred value_compare;
    typedef A allocator_type;
    typedef A::size_type size_type;
    typedef A::difference_type difference_type;
    typedef A::rebind<value_type>::other::const_reference reference;
    typedef A::rebind<value_type>::other::const_reference const_reference;
    typedef T0 iterator;
    typedef T1 const_iterator;
    typedef reverse_bidirectional_iterator<iterator,
        value_type, reference, A::pointer,
            difference_type> reverse_iterator;
    typedef reverse_bidirectional_iterator<const_iterator,
        value_type, const_reference, A::const_pointer,
            difference_type> const_reverse_iterator;
    explicit set(const Pred& comp = Pred(), const A& al = A());
    set(const set& x);
    set(const value_type *first, const value_type *last,
        const Pred& comp = Pred(), const A& al = A());
    const_iterator begin() const;
    iterator end() const;
    const_reverse_iterator rbegin() const;
    const_reverse_iterator rend() const;
    size_type size() const;
    size_type max_size() const;
    bool empty() const;
    A get_allocator() const;
    pair<iterator, bool> insert(const value_type& x);
    iterator insert(iterator it, const value_type& x);
    void insert(InIt first, InIt last);
    iterator erase(iterator it);
    iterator erase(iterator first, iterator last);
    size_type erase(const Key& key);
    void clear();
    void swap(set x);
    key_compare key_comp() const;
    value_compare value_comp() const;
    const_iterator find(const Key& key) const;
    size_type count(const Key& key) const;
    const_iterator lower_bound(const Key& key) const;
    const_iterator upper_bound(const Key& key) const;
    pair<const_iterator, const_iterator>
        equal_range(const Key& key) const;
protected:
    A allocator;
    };

The template class describes an object that controls a varying-length sequence of elements of type const Key. Each element serves as both a sort key and a value. The sequence is represented in a way that permits lookup, insertion, and removal of an arbitrary element with a number of operations proportional to the logarithm of the number of elements in the sequence (logarithmic time). Moreover, inserting an element invalidates no iterators, and removing an element invalidates only those iterators that point at the removed element.

The object orders the sequence it controls by calling a stored function object of type Pred. You access this stored object by calling the member function key_comp (). Such a function object must impose a total order on sort keys. For any element x that precedes y in the sequence, key_comp()(y, x) is false. (For the default function object less <Key>, sort keys never decrease in value.) Unlike template class multiset, an object of template class set ensures that key_comp()(x, y) is true. (Each key is unique.)

The object allocates and frees storage for the sequence it controls through a protected object named allocator, of class A. Such an allocator object must have the same external interface as an object of template class allocator. Note that allocator is not copied when the object is assigned.


set::allocator_type

typedef A allocator_type;

The type is a synonym for the template parameter A.


set::begin

const_iterator begin() const;

The member function returns a bidirectional iterator that points at the first element of the sequence (or just beyond the end of an empty sequence).

See the related sample program.


set::clear

void clear() const;

The member function calls erase ( begin (), end ()).

See the related sample program.


set::const_iterator

typedef T1 const_iterator;

The type describes an object that can serve as a constant bidirectional iterator for the controlled sequence. It is described here as a synonym for the unspecified type T1.


set::const_reference

typedef A::rebind<value_type>::other::const_reference const_reference;

The type describes an object that can serve as a constant reference to an element of the controlled sequence.


set::const_reverse_iterator

typedef reverse_bidirectional_iterator<const_iterator,
    value_type, const_reference, A::const_pointer,
        difference_type> const_reverse_iterator;

The type describes an object that can serve as a constant reverse bidirectional iterator for the controlled sequence.


set::count

size_type count(const Key& key) const;

The member function returns the number of elements x in the range [ lower_bound (key), upper_bound (key)).

See the related sample program.


set::difference_type

typedef A::difference_type difference_type;

The signed integer type describes an object that can represent the difference between the addresses of any two elements in the controlled sequence.


set::empty

bool empty() const;

The member function returns true for an empty controlled sequence.

See the related sample program.


set::end

const_iterator end() const;

The member function returns a bidirectional iterator that points just beyond the end of the sequence.

See the related sample program.


set::equal_range

pair<const_iterator, const_iterator>
    equal_range(const Key& key) const;

The member function returns a pair of iterators x such that x.first == lower_bound (key) and x.second == upper_bound (key).


set::erase

iterator erase(iterator it);
iterator erase(iterator first, iterator last);
size_type erase(const Key& key);

The first member function removes the element of the controlled sequence pointed to by it. The second member function removes the elements in the range [first, last). Both return an iterator that designates the first element remaining beyond any elements removed, or end () if no such element exists.

The third member removes the elements with sort keys in the range [ lower_bound (key), upper_bound (key)). It returns the number of elements it removes.


set::find

const_iterator find(const Key& key) const;

The member function returns an iterator that designates the earliest element in the controlled sequence whose sort key equals key. If no such element exists, the iterator equals end ().

See the related sample program.


set::get_allocator

A get_allocator() const;

The member function returns allocator.


set::insert

pair<iterator, bool> insert(const value_type& x);
iterator insert(iterator it, const value_type& x);
void insert(const value_type *first, const value_type *last);

The first member function determines whether an element y exists in the sequence whose key matches that of x. (The keys match if ! key_comp ()(x, y) && !key_comp()(y, x).) If not, it creates such an element y and initializes it with x. The function then determines the iterator it that designates y. If an insertion occurred, the function returns pair (it, true). Otherwise, it returns pair(it, false).

The second member function returns insert(x), using it as a starting place within the controlled sequence to search for the insertion point. (Insertion can occur in amortized constant time, instead of logarithmic time, if the insertion point immediately follows it.) The third member function inserts the sequence of element values in the range [first, last).

In this implementation, if a translator does not support member template functions, the template:

template<class InIt>
    void insert(InIt first, InIt last);

is replaced by:

void insert(const value_type *first, const value_type *last);


set::iterator

typedef T0 iterator;

The type describes an object that can serve as a bidirectional iterator for the controlled sequence. It is described here as a synonym for the unspecified type T0.


set::key_comp

key_compare key_comp() const;

The member function returns the stored function object that determines the order of elements in the controlled sequence. The stored object defines the member function:

bool operator(const Key& x, const Key& y);

which returns true if x strictly precedes y in the sort order.

See the related sample program.


set::key_compare

typedef Pred key_compare;

The type describes a function object that can compare two sort keys to determine the relative order of any two elements in the controlled sequence.


set::key_type

typedef Key key_type;

The type describes the sort key object that constitutes each element of the controlled sequence.


set::lower_bound

const_iterator lower_bound(const Key& key) const;

The member function returns an iterator that designates the earliest element x in the controlled sequence for which key_comp ()(x, key) is false.

If no such element exists, the function returns end ().


set::max_size

size_type max_size() const;

The member function returns the length of the longest sequence that the object can control.

See the related sample program.


set::rbegin

const_reverse_iterator rbegin() const;

The member function returns a reverse bidirectional iterator that points just beyond the end of the controlled sequence. Hence, it designates the beginning of the reverse sequence.

See the related sample program.


set::reference

typedef A::rebind<value_type>::other::const_reference reference;

The type describes an object that can serve as a reference to an element of the controlled sequence.


set::rend

const_reverse_iterator rend() const;

The member function returns a reverse bidirectional iterator that points at the first element of the sequence (or just beyond the end of an empty sequence). Hence, it designates the end of the reverse sequence.

See the related sample program.


set::reverse_iterator

typedef reverse_bidirectional_iterator<iterator,
    value_type, reference, A::pointer,
        difference_type> reverse_iterator;

The type describes an object that can serve as a reverse bidirectional iterator for the controlled sequence.


set::set

explicit set(const Pred& comp = Pred(), const A& al = A());
set(const set& x);
set(const value_type *first, const value_type *last,
    const Pred& comp = Pred(), const A& al = A());

The constructors with an argument named comp store the function object so that it can be later returned by calling key_comp (). All constructors also store the allocator object al (or, for the copy constructor, x. get_allocator ()) in allocator and initialize the controlled sequence. The first constructor specifies an empty initial controlled sequence. The second constructor specifies a copy of the sequence controlled by x. The last constructor specifies the sequence of element values [first, last).

In this implementation, if a translator does not support member template functions, the template:

template<class InIt>
    set(InIt first, InIt last,
        const Pred& comp = Pred(), const A& al = A());

is replaced by:

set(const value_type *first, const value_type *last,
    const Pred& comp = Pred(), const A& al = A());


set::size

size_type size() const;

The member function returns the length of the controlled sequence.

See the related sample program.


set::size_type

typedef A::size_type size_type;

The unsigned integer type describes an object that can represent the length of any controlled sequence.


set::swap

void swap(set& str);

The member function swaps the controlled sequences between *this and str. If allocator == str.allocator, it does so in constant time. Otherwise, it performs a number of element assignments and constructor calls proportional to the number of elements in the two controlled sequences.

See the related sample program.


set::upper_bound

const_iterator upper_bound(const Key& key) const;

The member function returns an iterator that designates the earliest element x in the controlled sequence for which key_comp ()(key, x) is true.

If no such element exists, the function returns end ().


set::value_comp

value_compare value_comp() const;

The member function returns a function object that determines the order of elements in the controlled sequence.

See the related sample program.


set::value_compare

typedef Pred value_compare;

The type describes a function object that can compare two elements as sort keys to determine their relative order in the controlled sequence.


set::value_type

typedef Key value_type;

The type describes an element of the controlled sequence.


swap

template<class Key, class Pred, class A>
    void swap(
        const multiset <Key, Pred, A>& lhs,
        const multiset <Key, Pred, A>& rhs);
template<class Key, class Pred, class A>
    void swap(
        const set <Key, Pred, A>& lhs,
        const set <Key, Pred, A>& rhs);

The template function executes lhs. swap (rhs).


 <sstream>

<sstream>

namespace std {
    template<class E,
        class T = char_traits<E>,
        class A = allocator<E> >
        class basic_stringbuf;
    typedef basic_stringbuf<char> stringbuf;
    typedef basic_stringbuf<wchar_t> wstringbuf;
    template<class E,
        class T = char_traits<E>,
        class A = allocator<E> >
        class basic_istringstream;
    typedef basic_istringstream<char> istringstream;
    typedef basic_istringstream<wchar_t> wistringstream;
    template<class E,
        class T = char_traits<E>,
        class A = allocator<E> >
        class basic_ostringstream;
    typedef basic_ostringstream<char> ostringstream;
    typedef basic_ostringstream<wchar_t> wostringstream;
    template<class E,
        class T = char_traits<E>,
        class A = allocator<E> >
        class basic_stringstream;
    typedef basic_stringstream<char> stringstream;
    typedef basic_stringstream<wchar_t> wstringstream;
    };

Include the iostreams standard header <sstream> to define several template classes that support iostreams operations on sequences stored in an allocated array object. Such sequences are easily converted to and from objects of template class basic_string.


basic_stringbuf

template <class E,
    class T = char_traits<E>,
    class A = allocator<E> >
    class basic_stringbuf {
public:
    basic_stringbuf(ios_base::openmode mode =
        ios_base::in | ios_base::out);
    basic_stringbuf(basic_string<E, T, A>& x,
        ios_base::openmode mode = ios_base::in | ios_base::out);
    basic_string<E, T, A> str() const;
    void str(basic_string<E, T, A>& x);
protected:
    virtual pos_type seekoff(off_type off, ios_base::seekdir way,
        ios_base::openmode mode = ios_base::in | ios_base::out);
    virtual pos_type seekpos(pos_type sp,
        ios_base::openmode mode = ios_base::in | ios_base::out);
    virtual int_type underflow();
    virtual int_type pbackfail(int_type c = T::eof());
    virtual int_type overflow(int_type c = T::eof());
    };

The template class describes a stream buffer that controls the transmission of elements to and from a sequence of elements stored in an array object. The object is allocated, extended, and freed as necessary to accommodate changes in the sequence.

An object of class basic_stringbuf<E, T, A> stores a copy of the ios_base:: openmode argument from its constructor as its stringbuf mode mode:

  • If mode & ios_base:: in is nonzero, the input buffer is accessible.
  • If mode & ios_base:: out is nonzero, the output buffer is accessible.


basic_stringbuf::basic_stringbuf

basic_stringbuf(ios_base::openmode mode =
    ios_base::in | ios_base::out);
basic_stringbuf(basic_string<E, T, A>& x,
    ios_base::openmode mode = ios_base::in | ios_base::out);

The first constructor stores a null pointer in all the pointers controlling the input buffer and the output buffer. It also stores mode as the stringbuf mode.

The second constructor allocates a copy of the sequence controlled by x, an object of class basic_string <E, T, A>. If mode & ios_base::in is nonzero, it sets the input buffer to begin reading at the start of the sequence. If mode & ios_base::out is nonzero, it sets the output buffer to begin writing at the start of the sequence. It also stores mode as the stringbuf mode.


basic_stringbuf::overflow

virtual int_type overflow(int_type c = T::eof());

If c does not compare equal to T:: eof (), the protected virtual member function endeavors to insert the element T:: to_char_type (c) into the output buffer. It can do so in various ways:

  • If a write position is available, it can store the element into the write position and increment the next pointer for the output buffer.
  • It can make a write position available by allocating new or additional storage for the output buffer. (Extending the output buffer this way also extends any associated input buffer.)

If the function cannot succeed, it returns T::eof(). Otherwise, it returns T:: not_eof (c).


basic_stringbuf::pbackfail

virtual int_type pbackfail(int_type c = T::eof());

The protected virtual member function endeavors to put back an element into the input buffer, then make it the current element (pointed to by the next pointer). If c compares equal to T:: eof (), the element to push back is effectively the one already in the stream before the current element. Otherwise, that element is replaced by x = T:: to_char_type (c). The function can put back an element in various ways:

  • If a putback position is available, and the element stored there compares equal to x, it can simply decrement the next pointer for the input buffer.
  • If a putback position is available, and if the stringbuf mode permits the sequence to be altered (mode & ios_base:: out is nonzero), it can store x into the putback position and decrement the next pointer for the input buffer.

If the function cannot succeed, it returns T::eof(). Otherwise, it returns T:: not_eof (c).


basic_stringbuf::seekoff

virtual pos_type seekoff(off_type off, ios_base::seekdir way,
    ios_base::openmode mode = ios_base::in | ios_base::out);

The protected virtual member function endeavors to alter the current positions for the controlled streams. For an object of class basic_stringbuf<E, T, A>, a stream position consists purely of a stream offset. Offset zero designates the first element of the controlled sequence.

The new position is determined as follows:

  • If way == ios_base:: beg, the new position is the beginning of the stream plus off.
  • If way == ios_base:: cur, the new position is the current stream position plus off.
  • If way == ios_base:: end, the new position is the end of the stream plus off.

If mode & ios_base::in is nonzero, the function alters the next position to read in the input buffer. If mode & ios_base::out is nonzero, the function alters the next position to write in the output buffer. For a stream to be affected, its buffer must exist. For a positioning operation to succeed, the resulting stream position must lie within the controlled sequence. If the function affects both stream positions, way must be ios_base::beg or ios_base::end and both streams must be positioned at the same element. Otherwise (or if neither position is affected), the positioning operation fails.

If the function succeeds in altering the stream position(s), it returns the resultant stream position. Otherwise, it fails and returns an invalid stream position.


basic_stringbuf::seekpos

virtual pos_type seekpos(pos_type sp,
    ios_base::openmode mode = ios_base::in | ios_base::out);

The protected virtual member function endeavors to alter the current positions for the controlled streams. For an object of class basic_stringbuf<E, T, A>, a stream position consists purely of a stream offset. Offset zero designates the first element of the controlled sequence. The new position is determined by sp.

If mode & ios_base::in is nonzero, the function alters the next position to read in the input buffer. If mode & ios_base::out is nonzero, the function alters the next position to write in the output buffer. For a stream to be affected, its buffer must exist. For a positioning operation to succeed, the resulting stream position must lie within the controlled sequence. Otherwise (or if neither position is affected), the positioning operation fails.

If the function succeeds in altering the stream position(s), it returns the resultant stream position. Otherwise, it fails and returns an invalid stream position.


basic_stringbuf::str

basic_string<E, T, A> str() const;
void str(basic_string<E, T, A>& x);

The first member function returns an object of class basic_string <E, T, allocator >, whose controlled sequence is a copy of the sequence controlled by *this. The sequence copied depends on the stored stringbuf mode mode:

  • If mode & ios_base:: out is nonzero and an output buffer exists, the sequence is the entire output buffer (epptr () - pbase () elements beginning with pbase()).
  • Otherwise, if mode & ios_base:: in is nonzero and an input buffer exists, the sequence is the entire input buffer (egptr () - eback () elements beginning with eback()).
  • Otherwise, the copied sequence is empty.

The second member function deallocates any sequence currently controlled by *this. It then allocates a copy of the sequence controlled by x. If mode & ios_base::in is nonzero, it sets the input buffer to begin reading at the beginning of the sequence. If mode & ios_base::out is nonzero, it sets the output buffer to begin writing at the beginning of the sequence.


basic_stringbuf::underflow

virtual int_type underflow();

The protected virtual member function endeavors to extract the current element c from the input buffer, then advance the current stream position, and return the element as T:: to_int_type (c). It can do so in only one way: If a read position is available, it takes c as the element stored in the read position and advances the next pointer for the input buffer.

If the function cannot succeed, it returns T:: eof (). Otherwise, it returns the current element in the input stream, converted as described above.


basic_istringstream

template <class E,
    class T = char_traits<E>,
    class A = allocator<E> >
    class basic_istringstream : public basic_istream<E, T> {
public:
    explicit basic_istringstream(ios_base::openmode mode = ios_base::in);
    explicit basic_istringstream(const basic_string<E, T, A>& x,
        ios_base::openmode mode = ios_base::in);
    basic_stringbuf<E, T, A> *rdbuf() const;
    basic_string<E, T, A>& str();
    void str(const basic_string<E, T, A>& x);
    };

The template class describes an object that controls extraction of elements and encoded objects from a stream buffer of class basic_stringbuf <E, T, A>, with elements of type E, whose character traits are determined by the class T, and whose elements are allocated by an allocator of class A. The object stores an object of class basic_stringbuf<E, T, A>.


basic_istringstream::basic_istringstream

explicit basic_istringstream(ios_base::openmode mode = ios_base::in);
explicit basic_istringstream(const basic_string<E, T, A>& x,
    ios_base::openmode mode = ios_base::in);

The first constructor initializes the base class by calling basic_istream (sb), where sb is the stored object of class basic_stringbuf <E, T, A>. It also initializes sb by calling basic_stringbuf <E, T, A>(mode | ios_base::in).

The second constructor initializes the base class by calling basic_istream(sb). It also initializes sb by calling basic_stringbuf <E, T, A>(x, mode | ios_base::in).


basic_istringstream::rdbuf

basic_stringbuf<E, T, A> *rdbuf() const

The member function returns the address of the stored stream buffer, of type pointer to basic_stringbuf <E, T, A>.


basic_istringstream::str

basic_string<E, T, A> str() const;
void str(basic_string<E, T, A>& x);

The first member function returns rdbuf ()-> str (). The second member function calls rdbuf()-> str(x).


basic_ostringstream

template <class E,
    class T = char_traits<E>,
    class A = allocator<E> >
    class basic_ostringstream : public basic_ostream<E, T> {
public:
    explicit basic_ostringstream(ios_base::openmode mode = ios_base::out);
    explicit basic_ostringstream(const basic_string<E, T, A>& x,
        ios_base::openmode mode = ios_base::out);
    basic_stringbuf<E, T, A> *rdbuf() const;
    basic_string<E, T, A>& str();
    void str(const basic_string<E, T, A>& x);
    };

The template class describes an object that controls insertion of elements and encoded objects into a stream buffer of class basic_stringbuf <E, T, A>, with elements of type E, whose character traits are determined by the class T, and whose elements are allocated by an allocator of class A. The object stores an object of class basic_stringbuf<E, T, A>.


basic_ostringstream::basic_ostringstream

explicit basic_ostringstream(ios_base::openmode mode = ios_base::out);
explicit basic_ostringstream(const basic_string<E, T, A>& x,
    ios_base::openmode mode = ios_base::out);

The first constructor initializes the base class by calling basic_ostream (sb), where sb is the stored object of class basic_stringbuf <E, T, A>. It also initializes sb by calling basic_stringbuf <E, T, A>(mode | ios_base::out).

The second constructor initializes the base class by calling basic_ostream(sb). It also initializes sb by calling basic_stringbuf <E, T, A>(x, mode | ios_base::out).


basic_ostringstream::rdbuf

basic_stringbuf<E, T, A> *rdbuf() const

The member function returns the address of the stored stream buffer, of type pointer to basic_stringbuf <E, T, A>.


basic_ostringstream::str

basic_string<E, T, A> str() const;
void str(basic_string<E, T, A>& x);

The first member function returns rdbuf ()-> str (). The second member function calls rdbuf()-> str(x).


basic_stringstream

template <class E,
    class T = char_traits<E>,
    class A = allocator<E> >
    class basic_stringstream : public basic_iostream<E, T> {
public:
    explicit basic_stringstream(ios_base::openmode mode = ios_base::in | ios_base::out);
    explicit basic_stringstream(const basic_string<E, T, A>& x,
        ios_base::openmode mode = ios_base::in | ios_base::out);
    basic_stringbuf<E, T, A> *rdbuf() const;
    basic_string<E, T, A>& str();
    void str(const basic_string<E, T, A>& x);
    };

The template class describes an object that controls insertion and extraction of elements and encoded objects using a stream buffer of class basic_stringbuf <E, T, A>, with elements of type E, whose character traits are determined by the class T, and whose elements are allocated by an allocator of class A. The object stores an object of class basic_stringbuf<E, T, A>.


basic_stringstream::basic_stringstream

explicit basic_stringstream(ios_base::openmode mode = ios_base::in | ios_base::out);
explicit basic_stringstream(const basic_string<E, T, A>& x,
    ios_base::openmode mode = ios_base::in | ios_base::out);

The first constructor initializes the base class by calling basic_iostream (sb), where sb is the stored object of class basic_stringbuf <E, T, A>. It also initializes sb by calling basic_stringbuf <E, T, A>(mode).

The second constructor initializes the base class by calling basic_ostream(sb). It also initializes sb by calling basic_stringbuf <E, T, A>(x, mode).


basic_stringstream::rdbuf

basic_stringbuf<E, T, A> *rdbuf() const

The member function returns the address of the stored stream buffer, of type pointer to basic_stringbuf <E, T, A>.


basic_stringstream::str

basic_string<E, T, A> str() const;
void str(basic_string<E, T, A>& x);

The first member function returns rdbuf ()-> str (). The second member function calls rdbuf()-> str(x).


istringstream

typedef basic_istringstream<char> istringstream;

The type is a synonym for template class basic_istringstream, specialized for elements of type char.


ostringstream

typedef basic_ostringstream<char> ostringstream;

The type is a synonym for template class basic_ostringstream, specialized for elements of type char.


stringbuf

typedef basic_stringbuf<char> stringbuf;

The type is a synonym for template class basic_stringbuf, specialized for elements of type char.


stringstream

typedef basic_stringstream<char> stringstream;

The type is a synonym for template class basic_stringstream, specialized for elements of type char.


wistringstream

typedef basic_istringstream<wchar_t> wistringstream;

The type is a synonym for template class basic_istringstream, specialized for elements of type wchar_t.


wostringstream

typedef basic_ostringstream<wchar_t> wostringstream;

The type is a synonym for template class basic_ostringstream, specialized for elements of type wchar_t.


wstringbuf

typedef basic_stringbuf<wchar_t> wstringbuf;

The type is a synonym for template class basic_stringbuf, specialized for elements of type wchar_t.


wstringstream

typedef basic_stringstream<wchar_t> wstringstream;

The type is a synonym for template class basic_stringstream, specialized for elements of type wchar_t.


 <stack>

<stack>

namespace std {
template<class T, class Cont>
    class stack;
//    TEMPLATE FUNCTIONS
template<class T, class Cont>
    bool operator==(const stack<T, Cont>& lhs,
        const stack<T, Cont>&);
template<class T, class Cont>
    bool operator!=(const stack<T, Cont>& lhs,
        const stack<T, Cont>&);
template<class T, class Cont>
    bool operator<(const stack<T, Cont>& lhs,
        const stack<T, Cont>&);
template<class T, class Cont>
    bool operator>(const stack<T, Cont>& lhs,
        const stack<T, Cont>&);
template<class T, class Cont>
    bool operator<=(const stack<T, Cont>& lhs,
        const stack<T, Cont>&);
template<class T, class Cont>
    bool operator>=(const stack<T, Cont>& lhs,
        const stack<T, Cont>&);
    };

Include the STL standard header <stack> to define the template class stack and two supporting templates.


operator!=

template<class T, class Cont>
    bool operator!=(const stack <T, Cont>& lhs,
        const stack <T, Cont>& rhs);

The template function returns !(lhs == rhs).


operator==

template<class T, class Cont>
    bool operator==(const stack <T, Cont>& lhs,
        const stack <T, Cont>& rhs);

The template function overloads operator== to compare two objects of template class stack. The function returns lhs. c == rhs.c.

See the related sample program.


operator<

template<class T, class Cont>
    bool operator<(const stack <T, Cont>& lhs,
        const stack <T, Cont>& rhs);

The template function overloads operator< to compare two objects of template class stack. The function returns lhs. c < rhs.c.

See the related sample program.


operator<=

template<class T, class Cont>
    bool operator<=(const stack <T, Cont>& lhs,
        const stack <T, Cont>& rhs);

The template function returns !(rhs < lhs).


operator>

template<class T, class Cont>
    bool operator>(const stack <T, Cont>& lhs,
        const stack <T, Cont>& rhs);

The template function returns rhs < lhs.


operator>=

template<class T, class Cont>
    bool operator>=(const stack <T, Cont>& lhs,
        const stack <T, Cont>& rhs);

The template function returns !(lhs < rhs).


stack

template<class T,
    class Cont = deque<T> >
    class stack {
public:
    typedef Cont::allocator_type allocator_type;
    typedef Cont::value_type value_type;
    typedef Cont::size_type size_type;
    explicit stack(const allocator_type& al = allocator_type()) const;
    bool empty() const;
    size_type size() const;
    allocator_type get_allocator() const;
    value_type& top();
    const value_type& top() const;
    void push(const value_type& x);
    void pop();
protected:
    Cont c;
    };

The template class describes an object that controls a varying-length sequence of elements. The object allocates and frees storage for the sequence it controls through a protected object named c, of class Cont. The type T of elements in the controlled sequence must match value_type.

An object of class Cont must supply several public members defined the same as for deque, list, and vector (all of which are suitable candidates for class Cont). The required members are:

    typedef T value_type;
    typedef T0 size_type;
    Cont(const allocator_type& al);
    bool empty() const;
    size_type size() const;
    allocator_type get_allocator() const;
    value_type& back();
    const value_type& back() const;
    void push_back(const value_type& x);
    void pop_back();

Here, T0 is an unspecified type that meets the stated requirements.


stack::allocator_type

typedef Cont::allocator_type allocator_type;

The type is a synonym for Cont::allocator_type.


stack::empty

bool empty() const;

The member function returns true for an empty controlled sequence.

See the related sample program.


stack::get_allocator

allocator_type get_allocator() const;

The member function returns c.get_allocator().


stack::pop

void pop();

The member function removes the last element of the controlled sequence, which must be non-empty.


stack::push

void push(const T& x);

The member function inserts an element with value x at the end of the controlled sequence.


stack::size

size_type size() const;

The member function returns the length of the controlled sequence.

See the related sample program.


stack::size_type

typedef Cont::size_type size_type;

The type is a synonym for Cont::size_type.


stack::stack

explicit stack(const allocator_type& al = allocator_type());

The constructor initializes the stored object with c (al), to specify an empty initial controlled sequence.


stack::top

value_type& top();
const value_type& top() const;

The member function returns a reference to the last element of the controlled sequence, which must be non-empty.

See the related sample program.


stack::value_type

typedef Cont::value_type value_type;

The type is a synonym for Cont::value_type.


 <stdexcept>

<stdexcept>

namespace std {
class logic_error;
    class domain_error;
    class invalid_argument;
    class length_error;
    class out_of_range;
class runtime_error;
    class range_error;
    class overflow_error;
    class underflow_error;
    };

Include the standard header <stdexcept> to define several classes used for reporting exceptions. The classes form a derivation hierarchy, as indicated by the indenting above, all derived from class exception.


domain_error

class domain_error : public logic_error {
public:
    domain_error(const string& what_arg);
    };

The class serves as the base class for all exceptions thrown to report a domain error. The value returned by what () is what_arg. data ().


invalid_argument

class invalid_argument : public logic_error {
public:
    invalid_argument(const string& what_arg);
    };

The class serves as the base class for all exceptions thrown to report an invalid argument. The value returned by what () is what_arg. data ().


length_error

class length_error : public logic_error {
public:
    length_error(const string& what_arg);
    };

The class serves as the base class for all exceptions thrown to report an attempt to generate an object too long to be specified. The value returned by what () is what_arg. data ().


logic_error

class logic_error : public exception {
public:
    logic_error(const string& what_arg);
    };

The class serves as the base class for all exceptions thrown to report errors presumably detectable before the program executes, such as violations of logical preconditions. The value returned by what () is what_arg. data ().


out_of_range

class out_of_range : public logic_error {
public:
    out_of_range(const string& what_arg);
    };

The class serves as the base class for all exceptions thrown to report an argument that is out of its valid range. The value returned by what () is what_arg. data ().


overflow_error

class overflow_error : public runtime_error {
public:
    overflow_error(const string& what_arg);
    };

The class serves as the base class for all exceptions thrown to report an arithmetic overflow. The value returned by what () is what_arg. data ().


range_error

class range_error : public runtime_error {
public:
    range_error(const string& what_arg);
    };

The class serves as the base class for all exceptions thrown to report a range error. The value returned by what () is what_arg. data ().


runtime_error

class runtime_error : public exception {
public:
    runtime_error(const string& what_arg);
    };

The class serves as the base class for all exceptions thrown to report errors presumably detectable only when the program executes. The value returned by what () is what_arg. data ().


underflow_error

class underflow_error : public runtime_error {
public:
    underflow_error(const string& what_arg);
    };

The class serves as the base class for all exceptions thrown to report an arithmetic underflow. The value returned by what () is what_arg. data ().


 <streambuf>

<streambuf>

namespace std {
    template<class E, class T = char_traits<E> >
        class basic_streambuf;
    typedef basic_streambuf<char, char_traits<char> > streambuf;
    typedef basic_streambuf<wchar_t, char_traits<wchar_t> > wstreambuf;
    };

Include the iostreams standard header <streambuf> to define template class basic_streambuf, which is basic to the operation of the iostreams classes. (This header is typically included for you by another of the iostreams headers. You seldom have occasion to include it directly.)


basic_streambuf

char_type · eback · egptr · epptr · gbump · getloc · gptr · imbue · in_avail · int_type · off_type · overflow · pbackfail · pbase · pbump · pos_type · pptr · pubimbue · pubseekoff · pubseekpos · pubsetbuf · pubsync · sbumpc · seekoff · seekpos · setbuf · setg · setp · sgetc · sgetn · showmanyc · snextc · sputbackc · sputc · sputn · sungetc · sync · traits_type · uflow · underflow · xsgetn · xsputn

template <class E, class T = char_traits<E> >
    class basic_streambuf {
public:
    typedef E char_type;
    typedef T traits_type;
    typedef T::int_type int_type;
    typedef T::pos_type pos_type;
    typedef T::off_type off_type;
    virtual ~streambuf();
    locale pubimbue(const locale& loc);
    locale getloc() const;
    basic_streambuf *pubsetbuf(E *s, streamsize n);
    pos_type pubseekoff(off_type off, ios_base::seekdir way,
        ios_base::openmode which = ios_base::in | ios_base::out);
    pos_type pubseekpos(pos_type sp,
        ios_base::openmode which = ios_base::in | ios_base::out);
    int pubsync();
    streamsize in_avail();
    int_type snextc();
    int_type sbumpc();
    int_type sgetc();
    streamsize sgetn(E *s, streamsize n);
    int_type sputbackc(E c);
    int_type sungetc();
    int_type sputc(E c);
    streamsize sputn(const E *s, streamsize n);
protected:
    basic_streambuf();
    E *eback() const;
    E *gptr() const;
    E *egptr() const;
    void gbump(int n);
    void setg(E *gbeg, E *gnext, E *gend);
    E *pbase() const;
    E *pptr() const;
    E *epptr() const;
    void pbump(int n);
    void setp(E *pbeg, E *pend);
    virtual void imbue(const locale &loc);
    virtual basic_streambuf *setbuf(E *s, streamsize n);
    virtual pos_type seekoff(off_type off, ios_base::seekdir way,
        ios_base::openmode which = ios_base::in | ios_base::out);
    virtual pos_type seekpos(pos_type sp,
        ios_base::openmode which = ios_base::in | ios_base::out);
    virtual int sync();
    virtual int showmanyc();
    virtual streamsize xsgetn(E *s, streamsize n);
    virtual int_type underflow();
    virtual int_type uflow();
    virtual int_type pbackfail(int_type c = T::eof());
    virtual streamsize xsputn(const E *s, streamsize n);
    virtual int_type overflow(int_type c = T::eof());
    };

The template class describes an abstract base class for deriving a stream buffer, which controls the transmission of elements to and from a specific representation of a stream. An object of class basic_streambuf<E, T> helps control a stream with elements of type E, whose character traits are determined by the class T.

Every stream buffer conceptually controls two independent streams, in fact, one for extractions (input) and one for insertions (output). A specific representation may, however, make either or both of these streams inaccessible. It typically maintains some relationship between the two streams. What you insert into the output stream of a basic_stringbuf <E, T> object, for example, is what you later extract from its input stream. When you position one stream of a basic_filebuf <E, T> object, you position the other stream in tandem.

The public interface to template class basic_streambuf supplies the operations common to all stream buffers, however specialized. The protected interface supplies the operations needed for a specific representation of a stream to do its work. The protected virtual member functions let you tailor the behavior of a derived stream buffer for a specific representation of a stream. Each of the derived stream buffers in the Standard C++ library describes how it specializes the behavior of its protected virtual member functions. Documented here is the default behavior for the base class, which is often to do nothing.

The remaining protected member functions control copying to and from any storage supplied to buffer transmissions to and from streams. An input buffer, for example, is characterized by:

  • eback (), a pointer to the beginning of the buffer
  • gptr (), a pointer to the next element to read
  • egptr (), a pointer just past the end of the buffer

Similarly, an output buffer is characterized by:

  • pbase (), a pointer to the beginning of the buffer
  • pptr (), a pointer to the next element to write
  • epptr (), a pointer just past the end of the buffer

For any buffer, the protocol is:

  • If the next pointer is null, no buffer exists. Otherwise, all three pointers point into the same sequence. (They can be safely compared for order.)
  • For an output buffer, if the next pointer compares less than the end pointer, you can store an element at the write position designated by the next pointer.
  • For an input buffer, if the next pointer compares less than the end pointer, you can read an element at the read position designated by the next pointer.
  • For an input buffer, if the beginning pointer compares less than the next pointer, you can put back an element at the putback position designated by the decremented next pointer.

Any protected virtual member functions you write for a class derived from basic_streambuf<E, T> must cooperate in maintaining this protocol.

An object of class basic_streambuf<E, T> stores the six pointers described above. It also stores a locale object in an object of type locale for potential use by a derived stream buffer.


basic_streambuf::basic_streambuf

basic_streambuf();

The protected constructor stores a null pointer in all the pointers controlling the input buffer and the output buffer. It also stores locale:: classic () in the locale object.


basic_streambuf::char_type

typedef E char_type;

The type is a synonym for the template parameter E.


basic_streambuf::eback

E *eback() const;

The member function returns a pointer to the beginning of the input buffer.


basic_streambuf::egptr

E *egptr() const;

The member function returns a pointer just past the end of the input buffer.


basic_streambuf::epptr

E *epptr() const;

The member function returns a pointer just past the end of the output buffer.


basic_streambuf::gbump

void gbump(int n);

The member function adds n to the next pointer for the input buffer.


basic_streambuf::getloc

locale getloc() const;

The member function returns the stored locale object.


basic_streambuf::gptr

E *gptr() const;

The member function returns a pointer to the next element of the input buffer.


basic_streambuf::imbue

virtual void imbue(const locale &loc);

The default behavior is to do nothing.


basic_streambuf::in_avail

streamsize in_avail();

If a read position is available, the member function returns egptr () - gptr (). Otherwise, it returns showmanyc ().


basic_streambuf::int_type

typedef T::int_type int_type;

The type is a synonym for T:: int_type.


basic_streambuf::off_type

typedef T::off_type off_type;

The type is a synonym for T:: off_type.


basic_streambuf::overflow

virtual int_type overflow(int_type c = T::eof());

If c does not compare equal to T:: eof (), the protected virtual member function endeavors to insert the element T:: to_char_type (c) into the output stream. It can do so in various ways:

  • If a write position is available, it can store the element into the write position and increment the next pointer for the output buffer.
  • It can make a write position available by allocating new or additional storage for the output buffer.
  • It can make a write position available by writing out, to some external destination, some or all of the elements between the beginning and next pointers for the output buffer.

If the function cannot succeed, it returns T::eof() or throws an exception. Otherwise, it returns T:: not_eof (c). The default behavior is to return T::eof().


basic_streambuf::pbackfail

virtual int_type pbackfail(int_type c = T::eof());

The protected virtual member function endeavors to put back an element into the input stream, then make it the current element (pointed to by the next pointer). If c compares equal to T:: eof (), the element to push back is effectively the one already in the stream before the current element. Otherwise, that element is replaced by T:: to_char_type (c). The function can put back an element in various ways:

  • If a putback position is available, it can store the element into the putback position and decrement the next pointer for the input buffer.
  • It can make a putback position available by allocating new or additional storage for the input buffer.
  • For a stream buffer with common input and output streams, it can make a putback position available by writing out, to some external destination, some or all of the elements between the beginning and next pointers for the output buffer.

If the function cannot succeed, it returns T::eof() or throws an exception. Otherwise, it returns some other value. The default behavior is to return T::eof().


basic_streambuf::pbase

E *pbase() const;

The member function returns a pointer to the beginning of the output buffer.


basic_streambuf::pbump

void pbump(int n);

The member function adds n to the next pointer for the output buffer.


basic_streambuf::pos_type

typedef T::pos_type pos_type;

The type is a synonym for T:: pos_type.


basic_streambuf::pptr

E *pptr() const;

The member function returns a pointer to the next element of the output buffer.


basic_streambuf::pubimbue

locale pubimbue(const locale& loc);

The member function stores loc in the locale object, calls imbue (), and then returns the previous value stored in the locale object.


basic_streambuf::pubseekoff

pos_type pubseekoff(off_type off, ios_base::seekdir way,
    ios_base::openmode which = ios_base::in | ios_base::out);

The member function returns seekoff (off, way, which).


basic_streambuf::pubseekpos

pos_type pubseekpos(pos_type sp,
    ios_base::openmode which = ios_base::in | ios_base::out);

The member function returns seekpos (sp, which).


basic_streambuf::pubsetbuf

basic_streambuf *pubsetbuf(E *s, streamsize n);

The member function returns setbuf (s, n).


basic_streambuf::pubsync

int pubsync();

The member function returns sync ().


basic_streambuf::sbumpc

int_type sbumpc();

If a read position is available, the member function returns T:: to_int_type ( * gptr ()) and increments the next pointer for the input buffer. Otherwise, it returns uflow ().


basic_streambuf::seekoff

virtual pos_type seekoff(off_type off, ios_base::seekdir way,
    ios_base::openmode which = ios_base::in | ios_base::out);

The protected virtual member function endeavors to alter the current positions for the controlled streams. The new position is determined as follows:

  • If way == ios_base:: beg, the new position is the beginning of the stream plus off.
  • If way == ios_base:: cur, the new position is the current stream position plus off.
  • If way == ios_base:: end, the new position is the end of the stream plus off.

Typically, if which & ios_base::in is nonzero, the input stream is affected, and if which & ios_base::out is nonzero, the output stream is affected. Actual use of this parameter varies among derived stream buffers, however.

If the function succeeds in altering the stream position(s), it returns the resultant stream position (or one of them). Otherwise, it returns an invalid stream position. The default behavior is to return an invalid stream position.


basic_streambuf::seekpos

virtual pos_type seekpos(pos_type sp,
    ios_base::openmode which = ios_base::in | ios_base::out);

The protected virtual member function endeavors to alter the current positions for the controlled streams. The new position is sp.

Typically, if which & ios_base::in is nonzero, the input stream is affected, and if which & ios_base::out is nonzero, the output stream is affected. Actual use of this parameter varies among derived stream buffers, however.

If the function succeeds in altering the stream position(s), it returns the resultant stream position (or one of them). Otherwise, it returns an invalid stream position. The default behavior is to return an invalid stream position.


basic_streambuf::setbuf

virtual basic_streambuf *setbuf(E *s, streamsize n);

The protected virtual member function performs an operation peculiar to each derived stream buffer. (See, for example, basic_filebuf.) The default behavior is to return this.


basic_streambuf::setg

void setg(E *gbeg, E *gnext, E *gend);

The member function stores gbeg in the beginning pointer, gnext in the next pointer, and gend in the end pointer for the input buffer.


basic_streambuf::setp

void setp(E *pbeg, E *pend);
void setp(E *pbeg, E *pnext, E *pend);

The member function stores pbeg in the beginning pointer, pnext in the next pointer, and pend in the end pointer for the output buffer.


basic_streambuf::sgetc

int_type sgetc();

If a read position is available, the member function returns T:: to_int_type ( * gptr ()) Otherwise, it returns underflow ().


basic_streambuf::sgetn

streamsize sgetn(E *s, streamsize n);

The member function returns sgetn (s, n).


basic_streambuf::showmanyc

virtual int showmanyc();

The protected virtual member function returns a count of the number of characters that can be extracted from the input stream without the program experiencing an indefinite wait. The default behavior is to return zero.


basic_streambuf::snextc

int_type snextc();

The member function calls sbumpc () and, if that function returns T:: eof (), returns T::eof(). Otherwise, it returns sgetc ().


basic_streambuf::sputbackc

int_type sputbackc(E c);

If a putback position is available and c compares equal to the character stored in that position, the member function decrements the next pointer for the input buffer and returns ch, which is the value T:: to_int_type (c). Otherwise, it returns pbackfail (ch).


basic_streambuf::sputc

int_type sputc(E c);

If a write position is available, the member function stores c in the write position, increments the next pointer for the output buffer, and returns ch, which is the value T:: to_int_type (c). Otherwise, it returns overflow (ch).


basic_streambuf::sputn

streamsize sputn(const E *s, streamsize n);

The member function returns sputn (s, n).


basic_streambuf::sungetc

int_type sungetc();

If a putback position is available, the member function decrements the next pointer for the input buffer and returns T:: to_int_type ( * gptr ()). Otherwise it returns pbackfail ().


basic_streambuf::sync

virtual int sync();

The protected virtual member function endeavors to synchronize the controlled streams with any associated external streams. Typically, this involves writing out any elements between the beginning and next pointers for the output buffer. It does not involve putting back any elements between the next and end pointers for the input buffer. If the function cannot succeed, it returns -1. The default behavior is to return zero.


basic_streambuf::traits_type

typedef T traits_type;

The type is a synonym for the template parameter T.


basic_streambuf::uflow

virtual int_type uflow();

The protected virtual member function endeavors to extract the current element c from the input stream, then advance the current stream position, and return the element as T:: to_int_type (c). It can do so in various ways:

  • If a read position is available, it takes c as the element stored in the read position and advances the next pointer for the input buffer.
  • It can read an element directly, from some external source, and deliver it as the value c.
  • For a stream buffer with common input and output streams, it can make a read position available by writing out, to some external destination, some or all of the elements between the beginning and next pointers for the output buffer. Or it can allocate new or additional storage for the input buffer. The function then reads in, from some external source, one or more elements.

If the function cannot succeed, it returns T:: eof (), or throws an exception. Otherwise, it returns the current element c in the input stream, converted as described above, and advances the next pointer for the input buffer. The default behavior is to call underflow () and, if that function returns T::eof(), to return T::eof(). Otherwise, the function returns the current element c in the input stream, converted as described above, and advances the next pointer for the input buffer.


basic_streambuf::underflow

virtual int_type underflow();

The protected virtual member function endeavors to extract the current element c from the input stream, without advancing the current stream position, and return it as T:: to_int_type (c). It can do so in various ways:

  • If a read position is available, c is the element stored in the read position.
  • It can make a read position available by allocating new or additional storage for the input buffer, then reading in, from some external source, one or more elements.

If the function cannot succeed, it returns T:: eof (), or throws an exception. Otherwise, it returns the current element in the input stream, converted as described above. The default behavior is to return T::eof().


basic_streambuf::xsgetn

virtual streamsize xsgetn(E *s, streamsize n);

The protected virtual member function extracts up to n elements from the input stream, as if by repeated calls to sbumpc, and stores them in the array beginning at s. It returns the number of elements actually extracted.


basic_streambuf::xsputn

virtual streamsize xsputn(const E *s, streamsize n);

The protected virtual member function inserts up to n elements into the output stream, as if by repeated calls to sputc, from the array beginning at s. It returns the number of elements actually inserted.


streambuf

typedef basic_streambuf<char, char_traits<char> > streambuf;

The type is a synonym for template class basic_streambuf, specialized for elements of type char with default character traits.


wstreambuf

typedef basic_streambuf<wchar_t, char_traits<wchar_t> > wstreambuf;

The type is a synonym for template class basic_streambuf, specialized for elements of type wchar_t with default character traits.


 <string>

<string>

basic_string · char_traits · char_traits<char> · char_traits<wchar_t> · getline · operator+ · operator!= · operator== · operator< · operator<< · operator<= · operator> · operator>= · operator>> · string · swap · wstring

namespace std {
//    TEMPLATE CLASSES
template<class E>
    struct char_traits;
struct char_traits<char>;
struct char_traits<wchar_t>;
template<class E,
    class T = char_traits<E>,
    class A = allocator<E> >
    class basic_string;
typedef basic_string<char> string;
typedef basic_string>wchar_t> wstring;
//    TEMPLATE FUNCTIONS
template<class E, class T, class A>
    basic_string<E, T, A> operator+(
        const basic_string<E, T, A>& lhs,
        const basic_string<E, T, A>& rhs);
template<class E, class T, class A>
    basic_string<E, T, A> operator+(
        const basic_string<E, T, A>& lhs,
        const E *rhs);
template<class E, class T, class A>
    basic_string<E, T, A> operator+(
        const basic_string<E, T, A>& lhs,
        E rhs);
template<class E, class T, class A>
    basic_string<E, T, A> operator+(
        const E *lhs,
        const basic_string<E, T, A>& rhs);
template<class E, class T, class A>
    basic_string<E, T, A> operator+(
        E lhs,
        const basic_string<E, T, A>& rhs);
template<class E, class T, class A>
    bool operator==(
        const basic_string<E, T, A>& lhs,
        const basic_string<E, T, A>& rhs);
template<class E, class T, class A>
    bool operator==(
        const basic_string<E, T, A>& lhs,
        const E *rhs);
template<class E, class T, class A>
    bool operator==(
        const E *lhs,
        const basic_string<E, T, A>& rhs);
template<class E, class T, class A>
    bool operator!=(
        const basic_string<E, T, A>& lhs,
        const basic_string<E, T, A>& rhs);
template<class E, class T, class A>
    bool operator!=(
        const basic_string<E, T, A>& lhs,
        const E *rhs);
template<class E, class T, class A>
    bool operator!=(
        const E *lhs,
        const basic_string<E, T, A>& rhs);
template<class E, class T, class A>
    bool operator<(
        const basic_string<E, T, A>& lhs,
        const basic_string<E, T, A>& rhs);
template<class E, class T, class A>
    bool operator<(
        const basic_string<E, T, A>& lhs,
        const E *rhs);
template<class E, class T, class A>
    bool operator<(
        const E *lhs,
        const basic_string<E, T, A>& rhs);
template<class E, class T, class A>
    bool operator>(
        const basic_string<E, T, A>& lhs,
        const basic_string<E, T, A>& rhs);
template<class E, class T, class A>
    bool operator>(
        const basic_string<E, T, A>& lhs,
        const E *rhs);
template<class E, class T, class A>
    bool operator>(
        const E *lhs,
        const basic_string<E, T, A>& rhs);
template<class E, class T, class A>
    bool operator<=(
        const basic_string<E, T, A>& lhs,
        const basic_string<E, T, A>& rhs);
template<class E, class T, class A>
    bool operator<=(
        const basic_string<E, T, A>& lhs,
        const E *rhs);
template<class E, class T, class A>
    bool operator<=(
        const E *lhs,
        const basic_string<E, T, A>& rhs);
template<class E, class T, class A>
    bool operator>=(
        const basic_string<E, T, A>& lhs,
        const basic_string<E, T, A>& rhs);
template<class E, class T, class A>
    bool operator>=(
        const basic_string<E, T, A>& lhs,
        const E *rhs);
template<class E, class T, class A>
    bool operator>=(
        const E *lhs,
        const basic_string<E, T, A>& rhs);
template<class E, class T, class A>
    void swap(
        const basic_string<E, T, A>& lhs,
        const basic_string<E, T, A>& rhs);
template<class E, class T, class A>
    basic_ostream<E>& operator<<(
        basic_ostream <E>& os,
        const basic_string<E, T, A>& str);
template<class E, class T, class A>
    basic_istream<E>& operator>>(
        basic_istream <E>& is,
        basic_string<E, T, A>& str);
template<class E, class T, class A>
    basic_istream<E, T>& getline(
        basic_istream <E, T>& is,
        basic_string<E, T, A>& str);
 template<class E, class T, class A>
    basic_istream<E, T>& getline(
        basic_istream <E, T>& is,
        basic_string<E, T, A>& str,
        E delim);
    };

Include the standard header <string> to define the container template class basic_string and various supporting templates.


basic_string

allocator_type · append · assign · at · basic_string · begin · c_str · capacity · char_type · compare · const_iterator · const_pointer · const_reference · const_reverse_iterator · copy · data · difference_type · empty · end · erase · find · find_first_not_of · find_first_of · find_last_not_of · find_last_of · get_allocator · insert · iterator · length · max_size · npos · operator+= · operator= · operator[] · pointer · rbegin · reference · rend · replace · reserve · resize · reverse_iterator · rfind · size · size_type · substr · swap · traits_type · value_type

template<class E,
    class T = char_traits<E>,
    class A = allocator<T> >
    class basic_string {
public:
    typedef T traits_type;
    typedef A allocator_type;
    typedef T::char_type char_type;
    typedef A::size_type size_type;
    typedef A::difference_type difference_type;
    typedef A::pointer pointer;
    typedef A::const_pointer const_pointer;
    typedef A::reference reference;
    typedef A::const_reference const_reference;
    typedef A::value_type value_type;
    typedef T0 iterator;
    typedef T1 const_iterator;
    typedef reverse_iterator<iterator, value_type,
        reference, pointer, difference_type>
            reverse_iterator;
    typedef reverse_iterator<const_iterator, value_type,
        const_reference, const_pointer, difference_type>
            const_reverse_iterator;
    static const size_type npos = -1;
    explicit basic_string(const A& al = A());
    basic_string(const basic_string& rhs);
    basic_string(const basic_string& rhs, size_type pos, size_type n,
        const A& al = A());
    basic_string(const E *s, size_type n, const A& al = A());
    basic_string(const E *s, const A& al = A());
    basic_string(size_type n, E c, const A& al = A());
    basic_string(const_iterator first, const_iterator last,
        const A& al = A());
    basic_string& operator=(const basic_string& rhs);
    basic_string& operator=(const E *s);
    basic_string& operator=(E c);
    iterator begin();
    const_iterator begin() const;
    iterator end();
    const_iterator end() const;
    reverse_iterator rbegin();
    const_reverse_iterator rbegin() const;
    reverse_iterator rend();
    const_reverse_iterator rend() const;
    const_reference at(size_type pos) const;
    reference at(size_type pos);
    const_reference operator[](size_type pos) const;
    reference operator[](size_type pos);
    const E *c_str() const;
    const E *data() const;
    size_type length() const;
    size_type size() const;
    size_type max_size() const;
    void resize(size_type n, E c = E());
    size_type capacity() const;
    void reserve(size_type n = 0);
    bool empty() const;
    basic_string& operator+=(const basic_string& rhs);
    basic_string& operator+=(const E *s);
    basic_string& operator+=(E c);
    basic_string& append(const basic_string& str);
    basic_string& append(const basic_string& str,
        size_type pos, size_type n);
    basic_string& append(const E *s, size_type n);
    basic_string& append(const E *s);
    basic_string& append(size_type n, E c);
    basic_string& append(const_iterator first, const_iterator last);
    basic_string& assign(const basic_string& str);
    basic_string& assign(const basic_string& str,
        size_type pos, size_type n);
    basic_string& assign(const E *s, size_type n);
    basic_string& assign(const E *s);
    basic_string& assign(size_type n, E c);
    basic_string& assign(const_iterator first, const_iterator last);
    basic_string& insert(size_type p0,
        const basic_string& str);
    basic_string& insert(size_type p0,
        const basic_string& str, size_type pos, size_type n);
    basic_string& insert(size_type p0,
        const E *s, size_type n);
    basic_string& insert(size_type p0, const E *s);
    basic_string& insert(size_type p0, size_type n, E c);
    iterator insert(iterator it, E c);
    void insert(iterator it, size_type n, E c);
    void insert(iterator it,
        const_iterator first, const_iterator last);
    basic_string& erase(size_type p0 = 0, size_type n = npos);
    iterator erase(iterator it);
    iterator erase(iterator first, iterator last);
    basic_string& replace(size_type p0, size_type n0,
        const basic_string& str);
    basic_string& replace(size_type p0, size_type n0,
        const basic_string& str, size_type pos, size_type n);
    basic_string& replace(size_type p0, size_type n0,
        const E *s, size_type n);
    basic_string& replace(size_type p0, size_type n0,
        const E *s);
    basic_string& replace(size_type p0, size_type n0,
        size_type n, E c);
    basic_string& replace(iterator first0, iterator last0,
        const basic_string& str);
    basic_string& replace(iterator first0, iterator last0,
        const E *s, size_type n);
    basic_string& replace(iterator first0, iterator last0,
        const E *s);
    basic_string& replace(iterator first0, iterator last0,
        size_type n, E c);
    basic_string& replace(iterator first0, iterator last0,
        const_iterator first, const_iterator last);
    size_type copy(E *s, size_type n, size_type pos = 0) const;
    void swap(basic_string& str);
    size_type find(const basic_string& str,
        size_type pos = 0) const;
    size_type find(const E *s, size_type pos, size_type n) const;
    size_type find(const E *s, size_type pos = 0) const;
    size_type find(E c, size_type pos = 0) const;
    size_type rfind(const basic_string& str,
        size_type pos = npos) const;
    size_type rfind(const E *s, size_type pos,
        size_type n = npos) const;
    size_type rfind(const E *s, size_type pos = npos) const;
    size_type rfind(E c, size_type pos = npos) const;
    size_type find_first_of(const basic_string& str,
        size_type pos = 0) const;
    size_type find_first_of(const E *s, size_type pos,
        size_type n) const;
    size_type find_first_of(const E *s, size_type pos = 0) const;
    size_type find_first_of(E c, size_type pos = 0) const;
    size_type find_last_of(const basic_string& str,
        size_type pos = npos) const;
    size_type find_last_of(const E *s, size_type pos,
        size_type n = npos) con/t;
    size_type find_last_of(const E *s, size_type pos = npos) const;
    size_type find_last_of(E c, size_type pos = npos) const;
    size_type find_first_not_of(const basic_string& str,
        size_type pos = 0) const;
    size_type find_first_not_of(const E *s, size_type pos,
        size_type n) const;
    size_type find_first_not_of(const E *s, size_type pos = 0) const;
    size_type find_first_not_of(E c, size_type pos = 0) const;
    size_type find_last_not_of(const basic_string& str,
        size_type pos = npos) const;
    size_type find_last_not_of(const E *s, size_type pos,
         size_type n) const;
    size_type find_last_not_of(const E *s,
        size_type pos = npos) const;
    size_type find_last_not_of(E c, size_type pos = npos) const;
    basic_string substr(size_type pos = 0, size_type n = npos) const;
    int compare(const basic_string& str) const;
    int compare(size_type p0, size_type n0,
        const basic_string& str);
    int compare(size_type p0, size_type n0,
        const basic_string& str, size_type pos, size_type n);
    int compare(const E *s) const;
    int compare(size_type p0, size_type n0,
        const E *s) const;
    int compare(size_type p0, size_type n0,
        const E *s, size_type pos) const;
    A get_allocator() const;
protected:
    A allocator;
    };

The template class describes an object that controls a varying-length sequence of elements of type E. Such an element type must not require explicit construction or destruction, and it must be suitable for use as the E parameter to basic_istream or basic_ostream. (A "plain old data structure," or POD, from C generally meets this criterion.) The Standard C++ library provides two specializations of this template class, with the type definitions string, for elements of type char, and wstring, for elements of type wchar_t.

Various important properties of the elements in a basic_string specialization are described by the class T. A class that specifies these character traits must have the same external interface as an object of template class char_traits.

The object allocates and frees storage for the sequence it controls through a protected object named allocator, of class A. Such an allocator object must have the same external interface as an object of template class allocator. (Class char_traits has no provision for alternative addressing schemes, such as might be required to implement a far heap.) Note that allocator is not copied when the object is assigned.

The sequences controlled by an object of template class basic_string are usually called strings. These objects should not be confused, however, with the null-terminated C strings used throughout the Standard C++ library.

Many member functions require an operand sequence of elements of type E. You can specify such an operand sequence several ways:

  • c -- a sequence of one element with value c
  • n, c -- a repetition of n elements each with value c
  • s -- a null-terminated sequence (such as a C string, for E of type char) beginning at s (which must not be a null pointer), where the terminating element is the value E(0) and is not part of the operand sequence
  • s, n -- a sequence of n elements beginning at s (which must not be a null pointer)
  • str -- the sequence specified by the basic_string object str
  • str, pos, n -- the substring of the basic_string object str with up to n elements (or through the end of the string, whichever comes first) beginning at position pos
  • first, last -- a sequence of elements delimited by the iterators first and last, in the range [first, last)

If a position argument (such as pos above) is beyond the end of the string on a call to a basic_string member function, the function reports an out-of-range error by throwing an object of class out_of_range.

If a function is asked to generate a sequence longer than max_size () elements, the function reports a length error by throwing an object of class length_error.


basic_string::allocator_type

typedef A allocator_type;

The type is a synonym for the template parameter A.


basic_string::append

basic_string& append(const E *s);
basic_string& append(const E *s, size_type n);
basic_string& append(const basic_string& str,
    size_type pos, size_type n);
basic_string& append(const basic_string& str);
basic_string& append(size_type n, E c);
basic_string& append(const_iterator first, const_iterator last);

The member template function appends the operand sequence to the end of the sequence controlled by *this, then returns *this.

In this implementation, if a translator does not support member template functions, the template:

template<class InIt>
    basic_string& append(InIt first, InIt last);

is replaced by:

basic_string& append(const_iterator first, const_iterator last);

See the related sample program.


basic_string::assign

basic_string& assign(const E *s);
basic_string& assign(const E *s, size_type n);
basic_string& assign(const basic_string& str,
    size_type pos, size_type n);
basic_string& assign(const basic_string& str);
basic_string& assign(size_type n, E c);
basic_string& assign(const_iterator first, const_iterator last);

Each member function replaces the sequence controlled by *this with the operand sequence, then returns *this.

In this implementation, if a translator does not support member template functions, the template:

template<class InIt>
    basic_string& assign(InIt first, InIt last);

is replaced by:

basic_string& assign(const_iterator first, const_iterator last);


basic_string::at

const_reference at(size_type pos) const;
reference at(size_type pos);

Each member function returns a reference to the element of the controlled sequence at position pos, or reports an out-of-range error.


basic_string::basic_string

basic_string(const E *s, const A& al = A());
basic_string(const E *s, size_type n, const A& al = A());
basic_string(const basic_string& rhs);
basic_string(const basic_string& rhs, size_type pos, size_type n,
    const A& al = A());
basic_string(size_type n, E c, const A& al = A());
explicit basic_string(const A& al = A());
basic_string(const_iterator first, const_iterator last,
    const A& al = A());

Each constructor stores the allocator object al (or, for the copy constructor, x. get_allocator ()) in allocator and initializes the controlled sequence to a copy of the operand sequence specified by the remaining operands. The explicit constructor specifies an empty initial controlled sequence.

In this implementation, if a translator does not support member template functions, the template:

template <class InIt>
    basic_string(InIt first, InIt last, const A& al = A());

is replaced by:

basic_string(const_iterator first, const_iterator last,
    const A& al = A());


basic_string::begin

const_iterator begin() const;
iterator begin();

Each member function returns a random-access iterator that points at the first element of the sequence (or just beyond the end of an empty sequence).


basic_string::c_str

const E *c_str() const;

The member function returns a pointer to a nonmodifiable C string constructed by adding a terminating null element (E(0)) to the controlled sequence. Calling any non-const member function for *this can invalidate the pointer.


basic_string::capacity

size_type capacity() const;

The member function returns the storage currently allocated to hold the controlled sequence, a value at least as large as size ().


basic_string::char_type

typedef T::char_type char_type;

The type is a synonym for the template parameter E.


basic_string::compare

int compare(const basic_string& str) const;
int compare(size_type p0, size_type n0,
    const basic_string& str);
int compare(size_type p0, size_type n0,
    const basic_string& str, size_type pos, size_type n);
int compare(const E *s) const;
int compare(size_type p0, size_type n0,
    const E *s) const;
int compare(size_type p0, size_type n0,
    const E *s, size_type pos) const;

Each member function compares up to n0 elements of the controlled sequence beginning with position p0, or the entire controlled sequence if these arguments are not supplied, to the operand sequence. The function returns:

  • A negative value if the first differing element in the controlled sequence compares less than the corresponding element in the operand sequence (as determined by T:: compare), or if the two have a common prefix but the operand sequence is longer.
  • Zero if the two compare equal element by element and are the same length.
  • A positive value otherwise.


basic_string::const_iterator

typedef T1 const_iterator;

The type describes an object that can serve as a constant random-access iterator for the controlled sequence. It is described here as a synonym for the unspecified type T1.


basic_string::const_pointer

typedef A::const_pointer const_pointer;

The type describes an object that can serve as a constant pointer to an element of the controlled sequence.


basic_string::const_reference

typedef A::const_reference const_reference;

The type describes an object that can serve as a constant reference to an element of the controlled sequence.


basic_string::const_reverse_iterator

typedef reverse_iterator<const_iterator, value_type,
    const_reference, const_pointer, difference_type>
        const_reverse_iterator;

The type describes an object that can serve as a constant reverse iterator for the controlled sequence.


basic_string::copy

size_type copy(E *s, size_type n, size_type pos = 0) const;

The member function copies up to n elements from the controlled sequence, beginning at position pos, to the array of E, beginning at s. It returns the number of elements actually copied.

See the related sample program.


basic_string::data

const E *data() const;

The member function returns a pointer to the first element of the sequence (or, for an empty sequence, a non-null pointer that cannot be dereferenced).


basic_string::difference_type

typedef A::difference_type difference_type;

The signed integer type describes an object that can represent the difference between the addresses of any two elements in the controlled sequence.


basic_string::empty

bool empty() const;

The member function returns true for an empty controlled sequence.


basic_string::end

const_iterator end() const;
iterator end();

Each member function returns a random-access iterator that points just beyond the end of the sequence.


basic_string::erase

iterator erase(iterator first, iterator last);
iterator erase(iterator it);
basic_string& erase(size_type p0 = 0, size_type n = npos);

The first member function removes the elements of the controlled sequence in the range [first, last). The second member function removes the element of the controlled sequence pointed to by it. Both return an iterator that designates the first element remaining beyond any elements removed, or end () if no such element exists.

The third member function removes up to n elements of the controlled sequence beginning at position p0, then returns *this.


basic_string::find

size_type find(E c, size_type pos = 0) const;
size_type find(const E *s, size_type pos = 0) const;
size_type find(const E *s, size_type pos, size_type n) const;
size_type find(const basic_string& str, size_type pos = 0) const;

Each member function finds the first (lowest beginning position) subsequence in the controlled sequence, beginning on or after position pos, that matches the operand sequence specified by the remaining operands. If it succeeds, it returns the position where the matching subsequence begins. Otherwise, the function returns npos.


basic_string::find_first_not_of

size_type find_first_not_of(E c, size_type pos = 0) const;
size_type find_first_not_of(const E *s, size_type pos = 0) const;
size_type find_first_not_of(const E *s, size_type pos,
    size_type n) const;
size_type find_first_not_of(const basic_string& str,
    size_type pos = 0) const;

Each member function finds the first (lowest position) element of the controlled sequence, at or after position pos, that matches none of the elements in the operand sequence specified by the remaining operands. If it succeeds, it returns the position. Otherwise, the function returns npos.


basic_string::find_first_of

size_type find_first_of(E c, size_type pos = 0) const;
size_type find_first_of(const E *s, size_type pos = 0) const;
size_type find_first_of(const E *s, size_type pos, size_type n) const;
size_type find_first_of(const basic_string& str,
    size_type pos = 0) const;

Each member function finds the first (lowest position) element of the controlled sequence, at or after position pos, that matches any of the elements in the operand sequence specified by the remaining operands. If it succeeds, it returns the position. Otherwise, the function returns npos.

See the related sample program.


basic_string::find_last_not_of

size_type find_last_not_of(E c, size_type pos = npos) const;
size_type find_last_not_of(const E *s, size_type pos = npos) const;
size_type find_last_not_of(const E *s, size_type pos,  size_type n) const;
size_type find_last_not_of(const basic_string& str,
    size_type pos = npos) const;

Each member function finds the last (highest position) element of the controlled sequence, at or before position pos, that matches none of the elements in the operand sequence specified by the remaining operands. If it succeeds, it returns the position. Otherwise, the function returns npos.


basic_string::find_last_of

size_type find_last_of(E c, size_type pos = npos) const;
size_type find_last_of(const E *s, size_type pos = npos) const;
size_type find_last_of(const E *s, size_type pos, size_type n = npos) const;
size_type find_last_of(const basic_string& str,
    size_type pos = npos) const;

Each member function finds the last (highest position) element of the controlled sequence, at or before position pos, that matches any of the elements in the operand sequence specified by the remaining operands. If it succeeds, it returns the position. Otherwise, the function returns npos.


basic_string::get_allocator

A get_allocator() const;

The member function returns allocator.


basic_string::insert

basic_string& insert(size_type p0, const E *s);
basic_string& insert(size_type p0, const E *s, size_type n);
basic_string& insert(size_type p0,
    const basic_string& str);
basic_string& insert(size_type p0,
    const basic_string& str, size_type pos, size_type n);
basic_string& insert(size_type p0, size_type n, E c);
iterator insert(iterator it, E c);
void insert(iterator it, const_iterator first, const_iterator last);
void insert(iterator it, size_type n, E c);

Each member function inserts, before position p0 or before the element pointed to by it in the controlled sequence, the operand sequence specified by the remaining operands. A function that returns a value returns *this.

In this implementation, if a translator does not support member template functions, the template:

template<class InIt>
    void insert(iterator it, InIt first, InIt last);

is replaced by:

void insert(iterator it, const_iterator first, const_iterator last);


basic_string::iterator

typedef T0 iterator;

The type describes an object that can serve as a random-access iterator for the controlled sequence. It is described here as a synonym for the unspecified type T0.


basic_string::length

size_type length() const;

The member function returns the length of the controlled sequence (same as size ()).


basic_string::max_size

size_type max_size() const;

The member function returns the length of the longest sequence that the object can control.


basic_string::npos

static const size_type npos = -1;

The constant is the largest representable value of type size_type. It is assuredly larger than max_size (); hence it serves as either a very large value or as a special code.


basic_string::operator+=

basic_string& operator+=(E c);
basic_string& operator+=(const E *s);
basic_string& operator+=(const basic_string& rhs);

Each operator appends the operand sequence to the end of the sequence controlled by *this, then returns *this.


basic_string::operator=

basic_string& operator=(E c);
basic_string& operator=(const E *s);
basic_string& operator=(const basic_string&nmp rhs);

Each operator replaces the sequence controlled by *this with the operand sequence, then returns *this.


basic_string::operator[]

const_reference operator[](size_type pos) const;
reference operator[](size_type pos);

Each member function returns a reference to the element of the controlled sequence at position pos. If that position is invalid, the behavior is undefined.


basic_string::pointer

typedef A::pointer pointer;

The type describes an object that can serve as a pointer to an element of the controlled sequence.


basic_string::rbegin

const_reverse_iterator rbegin() const;
reverse_iterator rbegin();

The member function returns a reverse iterator that points just beyond the end of the controlled sequence. Hence, it designates the beginning of the reverse sequence.


basic_string::reference

typedef A::reference reference;

The type describes an object that can serve as a reference to an element of the controlled sequence.


basic_string::rend

const_reverse_iterator rend() const;
reverse_iterator rend();

Each member function returns a reverse iterator that points at the first element of the sequence (or just beyond the end of an empty sequence). Hence, it designates the end of the reverse sequence.


basic_string::replace

basic_string& replace(size_type p0, size_type n0,
    const E *s);
basic_string& replace(size_type p0, size_type n0,
    const E *s, size_type n);
basic_string& replace(size_type p0, size_type n0,
    const basic_string& str);
basic_string& replace(size_type p0, size_type n0,
    const basic_string& str, size_type pos, size_type n);
basic_string& replace(size_type p0, size_type n0,
    size_type n, E c);
basic_string& replace(iterator first0, iterator last0,
    const E *s);
basic_string& replace(iterator first0, iterator last0,
    const E *s, size_type n);
basic_string& replace(iterator first0, iterator last0,
    const basic_string& str);
basic_string& replace(iterator first0, iterator last0,
    size_type n, E c);
basic_string& replace(iterator first0, iterator last0,
    const_iterator first, const_iterator last);

Each member function replaces up to n0 elements of the controlled sequence beginning with position p0, or the elements of the controlled sequence beginning with the one pointed to by first, up to but not including last. The replacement is the operand sequence specified by the remaining operands. The function then returns *this.

In this implementation, if a translator does not support member template functions, the template:

template<class InIt>
    basic_string& replace(iterator first0, iterator last0,
        InIt first, InIt last);

is replaced by:

basic_string& replace(iterator first0, iterator last0,
    const_iterator first, const_iterator last);


basic_string::reserve

void reserve(size_type n = 0);

The member function ensures that capacity () henceforth returns at least n.


basic_string::resize

void resize(size_type n, E c = E());

The member function ensures that size () henceforth returns n. If it must lengthen the controlled sequence, it appends elements with value c.

See the related sample program.


basic_string::reverse_iterator

typedef reverse_iterator<iterator, value_type,
    reference, pointer, difference_type>
        reverse_iterator;

The type describes an object that can serve as a reverse iterator for the controlled sequence.


basic_string::rfind

size_type rfind(E c, size_type pos = npos) const;
size_type rfind(const E *s, size_type pos = npos) const;
size_type rfind(const E *s, size_type pos, size_type n = npos) const;
size_type rfind(const basic_string& str,
    size_type pos = npos) const;

Each member function finds the last (highest beginning position) subsequence in the controlled sequence, beginning on or before position pos, that matches the operand sequence specified by the remaining operands. If it succeeds, it returns the position where the matching subsequence begins. Otherwise, the function returns npos.


basic_string::size

size_type size() const;

The member function returns the length of the controlled sequence.

See the related sample program.


basic_string::size_type

typedef A::size_type size_type;

The unsigned integer type describes an object that can represent the length of any controlled sequence.


basic_string::substr

basic_string substr(size_type pos = 0,
    size_type n = npos) const;

The member function returns an object whose controlled sequence is a copy of up to n elements of the controlled sequence beginning at position pos.


basic_string::swap

void swap(basic_string& str);

The member function swaps the controlled sequences between *this and str. If allocator == str.allocator, it does so in constant time. Otherwise, it performs a number of element assignments and constructor calls proportional to the number of elements in the two controlled sequences.


basic_string::traits_type

typedef T traits_type;

The type is a synonym for the template parameter T.


basic_string::value_type

typedef A::value_type value_type;

The type is a synonym for the template parameter E.


char_traits

struct char_traits<E> {
    typedef E char_type;
    typedef T1 int_type;
    typedef T2 pos_type;
    typedef T3 off_type;
    typedef T4 state_type;
    static void assign(E& x, const E& y);
    static E *assign(E *x, size_t n, const E& y);
    static bool eq(const E& x, const E& y);
    static bool lt(const E& x, const E& y);
    static int compare(const E *x, const E *y, size_t n);
    static size_t length(const E *x);
    static E *copy(E *x, const E *y, size_t n);
    static E *move(E *x, const E *y, size_t n);
    static const E *find(const E *x, size_t n, const E& y);
    static E to_char_type(const int_type& ch);
    static int_type to_int_type(const E& c);
    static bool eq_int_type(const int_type& ch1, const int_type& ch2);
    static int_type eof();
    static int_type not_eof(const int_type& ch);
    };

The template class describes various character traits for type E. The template class basic_string as well as several iostreams template classes, including basic_ios, use this information to manipulate elements of type E. Such an element type must not require explicit construction or destruction. A bitwise copy has the same effect as an assignment.


char_traits::assign

static void assign(E& x, const E& y);
static E *assign(E *x, size_t n, const E& y);

The first static member function assigns y to x. The second static member function assigns y to each element X[N] for N in the range [0, N).


char_traits::char_type

typedef E char_type;

The type is a synonym for the template parameter E.


char_traits::compare

static int compare(const E *x, const E *y, size_t n);

The static member function compares the sequence of length n beginning at x to the sequence of the same length beginning at y. The function returns:

  • A negative value if the first differing element in x (as determined by eq) compares less than the corresponding element in y (as determined by lt).
  • Zero if the two compare equal element by element.
  • A positive value otherwise.


char_traits::copy

static E *copy(E *x, const E *y, size_t n);

The static member function copies the sequence of n elements beginning at y to the array beginning at x, then returns x. The source and destination must not overlap.


char_traits::eof

static int_type eof();

The static member function returns a value that represents end-of-file (such as EOF or WEOF). If the value is also representable as type E, it must correspond to no valid value of that type.


char_traits::eq

static bool eq(const E& x, const E& y);

The static member function returns true if x compares equal to y.


char_traits::eq_int_type

static bool eq_int_type(const int_type& ch1, const int_type& ch2);

The static member function returns true if ch1 == ch2.


char_traits::find

static const E *find(const E *x, size_t n, const E& y);

The static member function determines the lowest N in the range [0, n) for which eq (x[N], y) is true. If successful, it returns x + N. Otherwise, it returns a null pointer.


char_traits::int_type

typedef T1 int_type;

The type is (typically) an integer type T1 that describes an object that can represent any element of the controlled sequence as well as the value returned by eof (). It must be possible to type cast a value of type E to int_type then back to E without altering the original value. In addition, the expression int_type('\0') must yield the code that terminates a null-terminated string for elements of type E. Also, the expression int_type('\n') must yield a suitable newline character of type E.


char_traits::length

static size_t length(const E *x);

The static member function returns the number of elements N in the sequence beginning at x up to but not including the element x[N] that compares equal to E(0).


char_traits::lt

static bool lt(const E& x, const E& y);

The static member function returns true if x compares less than y.


char_traits::move

static E *move(E *x, const E *y, size_t n);

The static member function copies the sequence of n elements beginning at y to the array beginning at x, and then returns x. The source and destination may overlap.


char_traits::not_eof

static int_type not_eof(const int_type& ch);

If ! eq_int_type ( eof (), ch), the static member function returns ch. Otherwise, it returns a value other than eof().


char_traits::off_type

typedef T3 off_type;

The type is a signed integer type T3 that describes an object that can store a byte offset involved in various stream positioning operations. It is typically a synonym for streamoff, but in any case it has essentially the same properties as that type.


char_traits::pos_type

typedef T2 pos_type;

The type is an opaque type T2 that describes an object that can store all the information needed to restore an arbitrary file-position indicator within a stream. It is typically a synonym for streampos, but in any case it has essentially the same properties as that type.


char_traits::state_type

typedef T4 state_type;

The type is an opaque type T4 that describes an object that can represent a conversion state. It is typically a synonym for mbstate_t, but in any case it has essentially the same properties as that type.


char_traits::to_char_type

static E to_char_type(const int_type& ch);

The static member function returns ch, represented as type E. A value of ch that cannot be so represented yields an unspecified result.


char_traits::to_int_type

static int_type to_int_type(const E& c);

The static member function returns ch, represented as type int_type. It should always be true that to_char_type (to_int_type(c) == c for any value of c.


char_traits<char>

class char_traits<char>;

The class is an explicit specialization of template class char_traits for elements of type char (so it can take advantage of library functions that manipulate objects of this type).


char_traits<wchar_t>

class char_traits<wchar_t>;

The class is an explicit specialization of template class char_traits for elements of type wchar_t (so it can take advantage of library functions that manipulate objects of this type).


getline

template<class E, class T, class A>
    basic_istream<E, T>& getline(
        basic_istream <E, T>& is,
        basic_string<E, T, A>& str);
template<class E, class T, class A>
    basic_istream<E, T>& getline(
        basic_istream <E, T>& is,
        basic_string<E, T, A>& str,
        E delim);

The first template function returns getline(is, str, is.widen('\n')).

The second template function replaces the sequence controlled by str with a sequence of elements extracted from the stream is. In order of testing, extraction stops:

  1. At end of file.
  2. After the function extracts an element that compares equal to delim, in which case the element is neither put back nor appended to the controlled sequence.
  3. After the function extracts is. max_size () elements, in which case the function calls setstate (ios_base::failbit).

If the function extracts no elements, it calls setstate(failbit). In any case, it returns *this.

See the related sample program.


operator+

template<class E, class T, class A>
    basic_string<E, T, A> operator+(
        const basic_string<E, T, A>& lhs,
        const basic_string<E, T, A>& rhs);
template<class E, class T, class A>
    basic_string<E, T, A> operator+(
        const basic_string<E, T, A>& lhs,
        const E *rhs);
template<class E, class T, class A>
    basic_string<E, T, A> operator+(
        const basic_string<E, T, A>& lhs,
        E rhs);
template<class E, class T, class A>
    basic_string<E, T, A> operator+(
        const E *lhs,
        const basic_string<E, T, A>& rhs);
template<class E, class T, class A>
    basic_string<E, T, A> operator+(
        E lhs,
        const basic_string<E, T, A>& rhs);

Each template function overloads operator+ to concatenate two objects of template class basic_string. All effectively return basic_string<E, T, A>(lhs). append (rhs).

See the related sample program.


operator!=

template<class E, class T, class A>
    bool operator!=(
        const basic_string<E, T, A>& lhs,
        const basic_string<E, T, A>& rhs);
template<class E, class T, class A>
    bool operator!=(
        const basic_string<E, T, A>& lhs,
        const E *rhs);
template<class E, class T, class A>
    bool operator!=(
        const E *lhs,
        const basic_string<E, T, A>& rhs);

Each template function overloads operator!= to compare two objects of template class basic_string. All effectively return basic_string<E, T, A>(lhs). compare (rhs) != 0.

See the related sample program.


operator==

template<class E, class T, class A>
    bool operator==(
        const basic_string<E, T, A>& lhs,
        const basic_string<E, T, A>& rhs);
template<class E, class T, class A>
    bool operator==(
        const basic_string<E, T, A>& lhs,
        const E *rhs);
template<class E, class T, class A>
    bool operator==(
        const E *lhs,
        const basic_string<E, T, A>& rhs);

Each template function overloads operator== to compare two objects of template class basic_string. All effectively return basic_string<E, T, A>(lhs). compare (rhs) == 0.

See the related sample program.


operator<

template<class E, class T, class A>
    bool operator<(
        const basic_string<E, T, A>& lhs,
        const basic_string<E, T, A>& rhs);
template<class E, class T, class A>
    bool operator<(
        const basic_string<E, T, A>& lhs,
        const E *rhs);
template<class E, class T, class A>
    bool operator<(
        const E *lhs,
        const basic_string<E, T, A>& rhs);

Each template function overloads operator< to compare two objects of template class basic_string. All effectively return basic_string<E, T, A>(lhs). compare (rhs) < 0.

See the related sample program.


operator<<

template<class E, class T, class A>
    basic_ostream<E, T>& operator<<(
        basic_ostream <E, T>& os,
        const basic_string<E, T, A>& str);

The template function overloads operator<< to insert an object str of template class basic_string into the stream os The function effectively returns os. write ( str. c_str (), str. size ()).

See the related sample program.


operator<=

template<class E, class T, class A>
    bool operator<=(
        const basic_string<E, T, A>& lhs,
        const basic_string<E, T, A>& rhs);
template<class E, class T, class A>
    bool operator<=(
        const basic_string<E, T, A>& lhs,
        const E *rhs);
template<class E, class T, class A>
    bool operator<=(
        const E *lhs,
        const basic_string<E, T, A>& rhs);

Each template function overloads operator<= to compare two objects of template class basic_string. All effectively return basic_string<E, T, A>(lhs). compare (rhs) <= 0.

See the related sample program.


operator>

template<class E, class T, class A>
    bool operator>(
        const basic_string<E, T, A>& lhs,
        const basic_string<E, T, A>& rhs);
template<class E, class T, class A>
    bool operator>(
        const basic_string<E, T, A>& lhs,
        const E *rhs);
template<class E, class T, class A>
    bool operator>(
        const E *lhs,
        const basic_string<E, T, A>& rhs);

Each template function overloads operator> to compare two objects of template class basic_string. All effectively return basic_string<E, T, A>(lhs). compare (rhs) > 0.

See the related sample program.


operator>=

template<class E, class T, class A>
    bool operator>=(
        const basic_string<E, T, A>& lhs,
        const basic_string<E, T, A>& rhs);
template<class E, class T, class A>
    bool operator>=(
        const basic_string<E, T, A>& lhs,
        const E *rhs);
template<class E, class T, class A>
    bool operator>=(
        const E *lhs,
        const basic_string<E, T, A>& rhs);

Each template function overloads operator>= to compare two objects of template class basic_string. All effectively return basic_string<E, T, A>(lhs). compare (rhs) >= 0.

See the related sample program.


operator>>

template<class E, class T, class A>
    basic_istream<E, T>& operator>>(
        basic_istream <E, T>& is,
        const basic_string<E, T, A>& str);

The template function overloads operator>> to replace the sequence controlled by str with a sequence of elements extracted from the stream is. Extraction stops:

  • At end of file.
  • After the function extracts is. width () elements, if that value is nonzero.
  • After the function extracts is. max_size () elements.
  • After the function extracts an element c for which use_facet < ctype <E> >( getloc ()). is ( ctype<E>:: space , c) is true, in which case the character is put back.

If the function extracts no elements, it calls setstate (ios_base::failbit). In any case, it calls width(0) and returns *this.

See the related sample program.


string

typedef basic_string<char> string;

The type describes a specialization of template class basic_string for elements of type char.


swap

template<class T, class A>
    void swap(
        const basic_string<E, T, A>& lhs,
        const basic_string<E, T, A>& rhs);

The template function executes swap (lhs, rhs).


wstring

typedef basic_string<wchar_t> wstring;

The type describes a specialization of template class basic_string for elements of type wchar_t.


 <strstream>

<strstream>

namespace std {
    class strstreambuf;
    class istrstream;
    class ostrstream;
    class strstream;
    };

Include the iostreams standard header <strstream> to define several classes that support iostreams operations on sequences stored in an allocated array of char object. Such sequences are easily converted to and from C strings.


strstreambuf

class strstreambuf : public streambuf {
public:
    explicit strstreambuf(streamsize n = 0);
    strstreambuf(void (*palloc)(size_t),
        void (*pfree)(void *));
    strstreambuf(char *gp, streamsize n,
        char *pp = 0);
    strstreambuf(signed char *gp, streamsize n,
        signed char *pp = 0);
    strstreambuf(unsigned char *gp, streamsize n,
        unsigned char *pp = 0);
    strstreambuf(const char *gp, streamsize n);
    strstreambuf(const signed char *gp, streamsize n);
    strstreambuf(const unsigned char *gp, streamsize n);
    void freeze(bool frz = true) const;
    char *str();
    streamsize pcount();
protected:
    virtual streampos seekoff(streamoff off, ios_base::seekdir way,
        ios_base::openmode which = ios_base::in | ios_base::out);
    virtual streampos seekpos(streampos sp,
        ios_base::openmode which = ios_base::in | ios_base::out);
    virtual int underflow();
    virtual int pbackfail(int c = EOF);
    virtual int overflow(int c = EOF);
    };

The class describes a stream buffer that controls the transmission of elements to and from a sequence of elements stored in a char array object. Depending on how it is constructed, the object can be allocated, extended, and freed as necessary to accommodate changes in the sequence.

An object of class strstreambuf stores several bits of mode information as its strstreambuf mode. These bits indicate whether the controlled sequence:

  • Has been allocated, and hence needs to be freed eventually.
  • Is modifiable.
  • Is extendable by reallocating storage.
  • Has been frozen and hence needs to be unfrozen before the object is destroyed, or freed (if allocated) by an agency other than the object.

A controlled sequence that is frozen cannot be modified or extended, regardless of the state of these separate mode bits.

The object also stores pointers to two functions that control strstreambuf allocation. If these are null pointers, the object devises its own method of allocating and freeing storage for the controlled sequence.


strstreambuf::freeze

void freeze(bool frz = true) const;

If frz is true, the function alters the stored strstreambuf mode to make the controlled sequence frozen. Otherwise, it makes the controlled sequence not frozen.


strstreambuf::pcount

streamsize pcount();

The member function returns a count of the number of elements written to the controlled sequence. Specifically, if pptr () is a null pointer, the function returns zero. Otherwise, it returns pptr() - pbase ().


strstreambuf::strstreambuf

explicit strstreambuf(streamsize n = 0);
strstreambuf(void (*palloc)(size_t),
    void (*pfree)(void *));
strstreambuf(char *gp, streamsize n,
    char *pp = 0);
strstreambuf(signed char *gp, streamsize n,
    signed char *pp = 0);
strstreambuf(unsigned char *gp, streamsize n,
    unsigned char *pp = 0);
strstreambuf(const char *gp, streamsize n);
strstreambuf(const signed char *gp, streamsize n);
strstreambuf(const unsigned char *gp, streamsize n);

The first constructor stores a null pointer in all the pointers controlling the input buffer, the output buffer, and strstreambuf allocation. It sets the stored strstreambuf mode to make the controlled sequence modifiable and extendable.

The second constructor behaves much as the first, except that it stores palloc as the pointer to the function to call to allocate storage, and pfree as the pointer to the function to call to free that storage.

The three constructors:

strstreambuf(char *gp, streamsize n,
    char *pp = 0);
strstreambuf(signed char *gp, streamsize n,
    signed char *pp = 0);
strstreambuf(unsigned char *gp, streamsize n,
    unsigned char *pp = 0);

also behave much as the first, except that gp designates the array object used to hold the controlled sequence. (Therefore, it must not be a null pointer.) The number of elements N in the array is determined as follows:

  • If (n > 0), then N is n.
  • If (n == 0), then N is strlen((const char *)gp).
  • If (n < 0), then N is INT_MAX.

If pp is a null pointer, the function establishes just an input buffer, by executing:

setg(gp, gp, gp + N);

Otherwise, it establishes both input and output buffers, by executing:

setg(gp, gp, pp);
setp(pp, gp + N);

In this case, pp must be in the interval [gp, gp + N].

Finally, the three constructors:

strstreambuf(const char *gp, streamsize n);
strstreambuf(const signed char *gp, streamsize n);
strstreambuf(const unsigned char *gp, streamsize n);

all behave the same as:

streambuf((char *)gp, n);

except that the stored mode makes the controlled sequence neither modifiable nor extendable.


strstreambuf::overflow

virtual int overflow(int c = EOF);

If c != EOF, the protected virtual member function endeavors to insert the element (char)c into the output buffer. It can do so in various ways:

  • If a write position is available, it can store the element into the write position and increment the next pointer for the output buffer.
  • If the stored strstreambuf mode says the controlled sequence is modifiable, extendable, and not frozen, the function can make a write position available by allocating new for the output buffer. (Extending the output buffer this way also extends any associated input buffer.)

If the function cannot succeed, it returns EOF. Otherwise, if c == EOF it returns some value other than EOF. Otherwise, it returns c.


strstreambuf::pbackfail

virtual int pbackfail(int c = EOF);

The protected virtual member function endeavors to put back an element into the input buffer, then make it the current element (pointed to by the next pointer).

If c == EOF, the element to push back is effectively the one already in the stream before the current element. Otherwise, that element is replaced by x = (char)c. The function can put back an element in various ways:

  • If a putback position is available, and the element stored there compares equal to x, it can simply decrement the next pointer for the input buffer.
  • If a putback position is available, and if the strstreambuf mode says the controlled sequence is modifiable, the function can store x into the putback position and decrement the next pointer for the input buffer.

If the function cannot succeed, it returns EOF. Otherwise, if c == EOF it returns some value other than EOF. Otherwise, it returns c.


strstreambuf::seekoff

virtual streampos seekoff(streamoff off, ios_base::seekdir way,
    ios_base::openmode which = ios_base::in | ios_base::out);

The protected virtual member function endeavors to alter the current positions for the controlled streams. For an object of class strstreambuf, a stream position consists purely of a stream offset. Offset zero designates the first element of the controlled sequence.

The new position is determined as follows:

  • If way == ios_base:: beg, the new position is the beginning of the stream plus off.
  • If way == ios_base:: cur, the new position is the current stream position plus off.
  • If way == ios_base:: end, the new position is the end of the stream plus off.

If which & ios_base::in is nonzero and the input buffer exists, the function alters the next position to read in the input buffer. If which & ios_base::out is also nonzero, way != ios_base::cur, and the output buffer exists, the function also sets the next position to write to match the next position to read.

Otherwise, if which & ios_base::out is nonzero and the output buffer exists, the function alters the next position to write in the output buffer. Otherwise, the positioning operation fails. For a positioning operation to succeed, the resulting stream position must lie within the controlled sequence.

If the function succeeds in altering the stream position(s), it returns the resultant stream position. Otherwise, it fails and returns an invalid stream position.


strstreambuf::seekpos

virtual streampos seekpos(streampos sp,
    ios_base::openmode which = ios_base::in | ios_base::out);

The protected virtual member function endeavors to alter the current positions for the controlled streams. For an object of class strstreambuf, a stream position consists purely of a stream offset. Offset zero designates the first element of the controlled sequence. The new position is determined by sp.

If which & ios_base::in is nonzero and the input buffer exists, the function alters the next position to read in the input buffer. (If which & ios_base::out is nonzero and the output buffer exists, the function also sets the next position to write to match the next position to read.) Otherwise, if which & ios_base::out is nonzero and the output buffer exists, the function alters the next position to write in the output buffer. Otherwise, the positioning operation fails. For a positioning operation to succeed, the resulting stream position must lie within the controlled sequence.

If the function succeeds in altering the stream position(s), it returns the resultant stream position. Otherwise, it fails and returns an invalid stream position.


strstreambuf::str

char *str();

The member function calls freeze (), then returns a pointer to the beginning of the controlled sequence. (Note that no terminating null element exists, unless you insert one explicitly.)


strstreambuf::underflow

virtual int underflow();

The protected virtual member function endeavors to extract the current element c from the input buffer, then advance the current stream position, and return the element as (int)(unsigned char)c. It can do so in only one way: If a read position is available, it takes c as the element stored in the read position and advances the next pointer for the input buffer.

If the function cannot succeed, it returns EOF. Otherwise, it returns the current element in the input stream, converted as described above.


istrstream

class istrstream : public istream {
public:
    explicit istrstream(const char *s);
    explicit istrstream(char *s);
    istrstream(const char *s, streamsize n);
    istrstream(char *s, streamsize n);
    strstreambuf *rdbuf() const;
    char *str();
    };

The class describes an object that controls extraction of elements and encoded objects from a stream buffer of class strstreambuf. The object stores an object of class strstreambuf.


istrstream::istrstream

explicit istrstream(const char *s);
explicit istrstream(char *s);
istrstream(const char *s, streamsize n);
istrstream(char *s, streamsize n);

All the constructors initialize the base class by calling istream (sb), where sb is the stored object of class strstreambuf. The first two constructors also initialize sb by calling strstreambuf ((const char *)s, 0). The remaining two constructors instead call strstreambuf((const char *)s, n).


istrstream::rdbuf

strstreambuf *rdbuf() const

The member function returns the address of the stored stream buffer, of type pointer to strstreambuf.


istrstream::str

char *str();

The member function returns rdbuf ()-> str ().


ostrstream

class ostrstream : public ostream {
public:
    ostrstream();
    ostrstream(char *s, streamsize n,
        ios_base::openmode mode = ios_base::out);
    strstreambuf *rdbuf() const;
    void freeze(bool frz = true);
    char *str();
    streamsize pcount() const;
    };

The class describes an object that controls insertion of elements and encoded objects into a stream buffer of class strstreambuf. The object stores an object of class strstreambuf.


ostrstream::freeze

void freeze(bool frz = true)

The member function calls rdbuf ()-> freeze (frz).


ostrstream::ostrstream

ostrstream();
ostrstream(char *s, streamsize n,
    ios_base::openmode mode = ios_base::out);

Both constructors initialize the base class by calling ostream (sb), where sb is the stored object of class strstreambuf. The first constructor also initializes sb by calling strstreambuf (). The second constructor initializes the base class one of two ways:

  • If mode & ios_base:: app == 0, then s must designate the first element of an array of n elements, and the constructor calls strstreambuf(s, n, s).
  • Otherwise, s must designate the first element of an array of n elements that contains a C string whose first element is designated by s, and the constructor calls strstreambuf(s, n, s + strlen(s).


ostrstream::pcount

streamsize pcount() const;

The member function returns rdbuf ()-> pcount ().


ostrstream::rdbuf

strstreambuf *rdbuf() const

The member function returns the address of the stored stream buffer, of type pointer to strstreambuf.


ostrstream::str

char *str();

The member function returns rdbuf ()-> str ().


strstream

class strstream : public iostream {
public:
    strstream();
    strstream(char *s, streamsize n,
        ios_base::openmode mode = ios_base::in | ios_base::out);
    strstreambuf *rdbuf() const;
    void freeze(bool frz = true);
    char *str();
    streamsize pcount() const;
    };

The class describes an object that controls insertion and extraction of elements and encoded objects using a stream buffer of class strstreambuf. The object stores an object of class strstreambuf.


strstream::freeze

void freeze(bool frz = true)

The member function calls rdbuf ()-> freeze (zfrz).


strstream::pcount

streamsize pcount() const;

The member function returns rdbuf ()-> pcount ().


strstream::strstream

strstream();
strstream(char *s, streamsize n,
    ios_base::openmode mode = ios_base::in | ios_base::out);

Both constructors initialize the base class by calling streambuf (sb), where sb is the stored object of class strstreambuf. The first constructor also initializes sb by calling strstreambuf (). The second constructor initializes the base class one of two ways:

  • If mode & ios_base:: app == 0, then s must designate the first element of an array of n elements, and the constructor calls strstreambuf(s, n, s).
  • Otherwise, s must designate the first element of an array of n elements that contains a C string whose first element is designated by s, and the constructor calls strstreambuf(s, n, s + strlen(s).


strstream::rdbuf

strstreambuf *rdbuf() const

The member function returns the address of the stored stream buffer, of type pointer to strstreambuf.


strstream::str

char *str();

The member function returns rdbuf ()-> str ().


 <utility>

<utility>

namespace std {
//      TEMPLATE CLASSES
template<class T, class U>
    struct pair;
//      TEMPLATE FUNCTIONS
template<class T, class U>
    pair<T, U> make_pair(const T& x, const U& y);
template<class T, class U>
    bool operator==(const pair<T, U>& x, const pair<T, U>& y);
template<class T, class U>
    bool operator!=(const pair<T, U>& x, const pair<T, U>& y);
template<class T, class U>
    bool operator<(const pair<T, U>& x, const pair<T, U>& y);
template<class T, class U>
    bool operator>(const pair<T, U>& x, const pair<T, U>& y);
template<class T, class U>
    bool operator<=(const pair<T, U>& x, const pair<T, U>& y);
template<class T, class U>
    bool operator>=(const pair<T, U>& x, const pair<T, U>& y);
namespace rel_ops {
    template<class T>
        bool operator!=(const T& x, const T& y);
    template<class T>
        bool operator<=(const T& x, const T& y);
    template<class T>
        bool operator>(const T& x, const T& y);
    template<class T>
        bool operator>=(const T& x, const T& y);
        };
    };

Include the STL standard header <utility> to define several templates of general use throughout the Standard Template Library.

Four template operators -- operator!=, operator<=, operator>, and operator>= -- define a total ordering on pairs of operands of the same type, given definitions of operator== and operator<.

If an implementation supports namespaces, these template operators are defined in the rel_ops namespace, nested within the std namespace. If you wish to use these template operators, write the declaration:

using namespace std::rel_ops;

which promotes the template operators into the current namespace.


make_pair

template<class T, class U>
    pair<T, U> make_pair(const T& x, const U& y);

The template function returns pair <T, U>(x, y).

See the related sample program.


operator!=

template<class T>
    bool operator!=(const T& x, const T& y);
template<class T, class U>
    bool operator!=(const pair<T, U>& x, const pair<T, U>& y);

The template function returns !(x == y).

See the related sample program.


operator==

template<class T, class U>
    bool operator==(const pair<T, U>& x, const pair<T, U>& y);

The template function returns x. first == y.first && x. second == y.second.

See the related sample program.


operator<

template<class T, class U>
    bool operator<(const pair<T, U>& x, const pair<T, U>& y);
template<class T, class U>
    bool operator<(const pair<T, U>& x, const pair<T, U>& y);

The template function returns x. first < y.first || !(y.first < x.first && x. second < y.second.

See the related sample program.


operator<=

template<class T>
    bool operator<=(const T& x, const T& y);
template<class T, class U>
    bool operator<=(const pair<T, U>& x, const pair<T, U>& y);

The template function returns !(y < x).

See the related sample program.


operator>

template<class T>
    bool operator>(const T& x, const T& y);
template<class T, class U>
    bool operator>(const pair<T, U>& x, const pair<T, U>& y);

The template function returns y < x.

See the related sample program.


operator>=

template<class T>
    bool operator>=(const T& x, const T& y);
template<class T, class U>
    bool operator>=(const pair<T, U>& x, const pair<T, U>& y);

The template function returns !(x < y).

See the related sample program.


pair

template<class T, class U>
    struct pair {
    typedef T first_type;
    typedef U second_type
    T first;
    U second;
    pair();
    pair(const T& x, const U& y);
    template<class V, class W>
        pair(const pair<V, W>& pr);
    };

The template class stores a pair of objects, first, of type T, and second, of type U. The type definition first_type is the same as the template parameter T, while second_type is the same as the template parameter U.

The first (default) constructor initializes first to T() and second to U(). The second constructor initializes first to x and second to y. The third (template) constructor initializes first to pr.first and second to pr.second. T and U each need supply only a single-argument constructor and a destructor.


 <valarray>

<valarray>

gslice · gslice_array · indirect_array · mask_array · slice · slice_array · valarray · valarray<bool>

abs · acos · asin · atan · atan2 · cos · cosh · exp · log · log10 · max · min · operator!= · operator% · operator& · operator&& · operator> · operator>> · operator>= · operator< · operator<< · operator<= · operator* · operator+ · operator- · operator/ · operator== · operator^ · operator| · operator|| · pow · sin · sinh · sqrt · tan · tanh

namespace std {
class slice;
class gslice;
        // TEMPLATE CLASSES
template<class T>
    class valarray;
template<class T>
    class slice_array;
template<class T>
    class gslice_array;
template<class T>
    class mask_array;
template<class T>
    class indirect_array;
        // TEMPLATE FUNCTIONS
template<class T>
    valarray<T> operator*(const valarray<T>& lhs,
        const valarray<T>& rhs);
template<class T>
    valarray<T> operator*(const valarray<T> lhs,
        const T& rhs);
template<class T>
    valarray<T> operator*(const T& lhs, const valarray<T>& rhs);
template<class T>
    valarray<T> operator/(const valarray<T>& lhs,
        const valarray<T>& rhs);
template<class T>
    valarray<T> operator/(const valarray<T> lhs, const T& rhs);
template<class T>
    valarray<T> operator/(const T& lhs, const valarray<T>& rhs);
template<class T>
    valarray<T> operator%(const valarray<T>& lhs,
        const vararray<T>& rhs);
template<class T>
    valarray<T> operator%(const valarray<T> lhs, const T& rhs);
template<class T>
    valarray<T> operator%(const T& lhs, const valarray<T>& rhs);
template<class T>
    valarray<T> operator+(const valarray<T>& lhs,
        const valarray<T>& rhs);
template<class T>
    valarray<T> operator+(const valarray<T> lhs, const T& rhs);
template<class T>
    valarray<T> operator+(const T& lhs, const valarray<T>& rhs);
template<class T>
    valarray<T> operator-(const valarray<T>& lhs,
        const valarray<T>& rhs);
template<class T>
    valarray<T> operator-(const valarray<T> lhs, const T& rhs);
template<class T>
    valarray<T> operator-(const T& lhs, const valarray<T>& rhs);
template<class T>
    valarray<T> operator^(const valarray<T>& lhs,
        const valarray<T>& rhs);
template<class T>
    valarray<T> operator^(const valarray<T> lhs, const T& rhs);
template<class T>
    valarray<T> operator^(const T& lhs, const valarray<T>& rhs);
template<class T>
    valarray<T> operator&(const valarray<T>& lhs,
        const valarray<T>& rhs);
template<class T>
    valarray<T> operator&(const valarray<T> lhs, const T& rhs);
template<class T>
    valarray<T> operator&(const T& lhs, const valarray<T>& rhs);
template<class T>
    valarray<T> operator|(const valarray<T>& lhs,
        const valarray<T>& rhs);
template<class T>
    valarray<T> operator|(const valarray<T> lhs, const T& rhs);
template<class T>
    valarray<T> operator|(const T& lhs, const valarray<T>& rhs);
template<class T>
    valarray<T> operator<<(const valarray<T>& lhs,
        const valarray<T>& rhs);
template<class T>
    valarray<T> operator<<(const valarray<T> lhs, const T& rhs);
template<class T>
    valarray<T> operator<<(const T& lhs, const valarray<T>& rhs);
template<class T>
    valarray<T> operator>>(const valarray<T>& lhs,
        const valarray<T>& rhs);
template<class T>
    valarray<T> operator>>(const valarray<T> lhs, const T& rhs);
template<class T>
    valarray<T> operator>>(const T& lhs, const valarray<T>& rhs);
template<class T>
    valarray<bool> operator&&(const valarray<T>& lhs,
        const valarray<T>& rhs);
template<class T>
    valarray<bool> operator&&(const valarray<T> lhs, const T& rhs);
template<class T>
    valarray<bool> operator&&(const T& lhs, const valarray<T>& rhs);
template<class T>
    valarray<biil> operator||(const valarray<T>& lhs,
        const valarray<T>& rhs);
template<class T>
    valarray<bool> operator||(const valarray<T> lhs, const T& rhs);
template<class T>
    valarray<bool> operator||(const T& lhs, const valarray<T>& rhs);
template<class T>
    valarray<bool> operator==(const valarray<T>& lhs,
        const valarray<T>& rhs);
template<class T>
    valarray<bool> operator==(const valarray<T> lhs, const T& rhs);
template<class T>
    valarray<bool> operator==(const T& lhs, const valarray<T>& rhs);
template<class T>
    valarray<bool> operator!=(const valarray<T>& lhs,
        const valarray<T>& rhs);
template<class T>
    valarray<bool> operator!=(const valarray<T> lhs, const T& rhs);
template<class T>
    valarray<bool> operator!=(const T& lhs, const valarray<T>& rhs);
template<class T>
    valarray<bool> operator<(const valarray<T>& lhs,
        const valarray<T>& rhs);
template<class T>
    valarray<bool> operator<(const valarray<T> lhs, const T& rhs);
template<class T>
    valarray<bool> operator<(const T& lhs, const valarray<T>& rhs);
template<class T>
    valarray<bool> operator>=(const valarray<T>& lhs,
        const valarray<T>& rhs);
template<class T>
    valarray<bool> operator>=(const valarray<T> lhs, const T& rhs);
template<class T>
    valarray<bool> operator>=(const T& lhs, const valarray<T>& rhs);
template<class T>
    valarray<bool> operator>(const valarray<T>& lhs,
        const valarray<T>& rhs);
template<class T>
    valarray<bool> operator>(const valarray<T> lhs, const T& rhs);
template<class T>
    valarray<bool> operator>(const T& lhs, const valarray<T>& rhs);
template<class T>
    valarray<bool> operator<=(const valarray<T>& lhs,
        const valarray<T>& rhs);
template<class T>
    valarray<bool> operator<=(const valarray<T> lhs, const T& rhs);
template<class T>
    valarray<bool> operator<=(const T& lhs, const valarray<T>& rhs);
template<class T>
    T max(const valarray<T>& x);
template<class T>
    T min(const valarray<T>& x);
template<class T>
    valarray<T> abs(const valarray<T>& x);
template<class T>
    valarray<T> acos(const valarray<T>& x);
template<class T>
    valarray<T> asin(const valarray<T>& x);
template<class T>
    valarray<T> atan(const valarray<T>& x);
template<class T>
    valarray<T> atan2(const valarray<T>& x,
        const valarray<T>& y);
template<class T>
    valarray<T> atan2(const valarray<T> x, const T& y);
template<class T>
    valarray<T> atan2(const T& x, const valarray<T>& y);
template<class T>
    valarray<T> cos(const valarray<T>& x);
template<class T>
    valarray<T> cosh(const valarray<T>& x);
template<class T>
    valarray<T> exp(const valarray<T>& x);
template<class T>
    valarray<T> log(const valarray<T>& x);
template<class T>
    valarray&ttT> log10(const valarray<T>& x);
template<class T>
    valarray<T> pow(const valarray<T>& x,
        const valarray<T>& y);
template<class T>
    valarray<T> pow(const valarray<T> x, const T& y);
template<class T>
    valarray<T> pow(const T& x, const valarray<T>& y);
template<class T>
    valarray<T> sin(const valarray<T>& x);
template<class T>
    valarray<T> sinh(const valarray<T>& x);
template<class T>
    valarray<T> sqrt(const valarray<T>& x);
template<class T>
    valarray<T> tan(const valarray<T>& x);
template<class T>
    valarray<T> tanh(const valarray<T>& x);
    };

Include the standard header <valarray> to define the template class valarray and numerous supporting template classes and functions. These template classes and functions are permitted unusual latitude, in the interest of improved performance. Specifically, any function returning valarray<T> may return an object of some other type T'. In that case, any function that accepts one or more arguments of type valarray<T> must have overloads that accept arbitrary combinations of those arguments, each replaced with an argument of type T'. (Put simply, the only way you can detect such a substitution is to go looking for it.)


abs

template<class T>
    valarray<T> abs(const valarray<T>& x);

The template function returns an object of class valarray <T>, each of whose elements I is the absolute value of x[I].

See the related sample program.


acos

template<class T>
    valarray<T> acos(const valarray<T>& x);

The template function returns an object of class valarray <T>, each of whose elements I is the arccosine of x[I].

See the related sample program.


asin

template<class T>
    valarray<T> asin(const valarray<T>& x);

The template function returns an object of class valarray <T>, each of whose elements I is the arcsine of x[I].

See the related sample program.


atan

template<class T>
    valarray<T> atan(const valarray<T>& x);

The template function returns an object of class valarray <T>, each of whose elements I is the arctangent of x[I].

See the related sample program.


atan2

template<class T>
    valarray<T> atan2(const valarray<T>& x,
        const valarray<T>& y);
template<class T>
    valarray<T> atan2(const valarray<T> x, const T& y);
template<class T>
    valarray<T> atan2(const T& x, const valarray<T>& y);

The first template function returns an object of class valarray <T>, each of whose elements I is the arctangent of x[I] / y[I]. The second template function stores in element I the arctangent of x[I] / y. The third template function stores in element I the arctangent of x / y[I].


cos

template<class T>
    valarray<T> cos(const valarray<T>& x);

The template function returns an object of class valarray <T>, each of whose elements I is the cosine of x[I].

See the related sample program.


cosh

template<class T>
    valarray<T> cosh(const valarray<T>& x);

The template function returns an object of class valarray <T>, each of whose elements I is the hyperbolic cosine of x[I].

See the related sample program.


exp

template<class T>
    valarray<T> exp(const valarray<T>& x);

The template function returns an object of class valarray <T>, each of whose elements I is the exponential of x[I].

See the related sample program.


gslice

class gslice {
public:
    gslice();
    gslice(size_t st,
        const valarray<size_t> len, const valarray<size_t> str);
    size_t start() const;
    const valarray<size_t> size() const;
    const valarray<size_t> stride() const;
    };

The class stores the parameters that characterize a gslice_array when an object of class gslice appears as a subscript for an object of class valarray <T>. The stored values include:

  • A starting index
  • A length vector of class valarray<size_t>
  • A stride vector of class valarray<size_t>

The two vectors must have the same length.


gslice::gslice

gslice();
gslice(size_t st,
    const valarray<size_t> len, const valarray<size_t> str);

The default constructor stores zero for the starting index, and zero-length vectors for the length and stride vectors. The second constructor stores st for the starting index, len for the length vector, and str for the stride vector.


gslice::size

const valarray<size_t> size() const;

The member function returns the stored length vector.


gslice::start

size_t start() const;

The member function returns the stored starting index.


gslice::stride

const valarray<size_t> stride() const;

The member function returns the stored stride vector.


gslice_array

template<class T>
    class gslice_array {
public:
    typedef T value_type;
    void operator=(const valarray<T> x) const;
    void operator=(const T& x);
    void operator*=(const valarray<T> x) const;
    void operator/=(const valarray<T> x) const;
    void operator%=(const valarray<T> x) const;
    void operator+=(const valarray<T> x) const;
    void operator-=(const valarray<T> x) const;
    void operator^=(const valarray<T> x) const;
    void operator&=(const valarray<T> x) const;
    void operator|=(const valarray<T> x) const;
    void operator<<=(const valarray<T> x) const;
    void operator>>=(const valarray<T> x) const;
    void fill();
    };

The class describes an object that stores a reference to an object x of class valarray <T>, along with an object gs of class gslice, which describes the sequence of elements to select from the valarray<T> object.

You construct a gslice_array<T> object only by writing an expression of the form x[gs]. The member functions of class gslice_array then behave like the corresponding function signatures defined for valarray<T>, except that only the sequence of selected elements is affected.

The sequence is determined as follows. For a length vector gs. size () of length N, construct the index vector valarray<size_t> idx(0, N). This designates the initial element of the sequence, whose index k within x is given by the mapping:

k = start;
for (size_t i = 0; i < gs.size()[i]; ++i)
    k += idx[i] * gs.stride()[i];

The successor to an index vector value is given by:

for (size_t i = N; 0 < i--; )
    if (++idx[i] < gs.size()[i])
        break;
    else
        idx[i] = 0;

For example:

const size_t lv[] = {2, 3};
const size_t dv[] = {7, 2};
const valarray<size_t> len(lv, 2), str(dv, 2);
// x[gslice(3, len, str)] selects elements with indices
//   3, 5, 7, 10, 12, 14


indirect_array

template<class T>
    class indirect_array {
public:
    typedef T value_type;
    void operator=(const valarray<T> x) const;
    void operator=(const T& x);
    void operator*=(const valarray<T> x) const;
    void operator/=(const valarray<T> x) const;
    void operator%=(const valarray<T> x) const;
    void operator+=(const valarray<T> x) const;
    void operator-=(const valarray<T> x) const;
    void operator^=(const valarray<T> x) const;
    void operator&=(const valarray<T> x) const;
    void operator|=(const valarray<T> x) const;
    void operator<<=(const valarray<T> x) const;
    void operator>>=(const valarray<T> x) const;
    void fill();
    };

The class describes an object that stores a reference to an object x of class valarray <T>, along with an object xa of class valarray<size_t>, which describes the sequence of elements to select from the valarray<T> object.

You construct an indirect_array<T> object only by writing an expression of the form x[xa]. The member functions of class indirect_array then behave like the corresponding function signatures defined for valarray<T>, except that only the sequence of selected elements is affected.

The sequence consists of xa. size () elements, where element i becomes the index xa[i] within x. For example:

const size_t vi[] = {7, 5, 2, 3, 8};
// x[valarray<size_t>(vi, 5)] selects elements with indices
//   7, 5, 2, 3, 8


log

template<class T>
    valarray<T> log(const valarray<T>& x);

The template function returns an object of class valarray <T>, each of whose elements I is the natural logarithm of x[I].

See the related sample program.


log10

template<class T>
    valarray<T> log10(const valarray<T>& x);

The template function returns an object of class valarray <T>, each of whose elements I is the base-10 logarithm of x[I].

See the related sample program.


mask_array

template<class T>
    class mask_array {
public:
    typedef T value_type;
    void operator=(const valarray<T> x) const;
    void operator=(const T& x);
    void operator*=(const valarray<T> x) const;
    void operator/=(const valarray<T> x) const;
    void operator%=(const valarray<T> x) const;
    void operator+=(const valarray<T> x) const;
    void operator-=(const valarray<T> x) const;
    void operator^=(const valarray<T> x) const;
    void operator&=(const valarray<T> x) const;
    void operator|=(const valarray<T> x) const;
    void operator<<=(const valarray<T> x) const;
    void operator>>=(const valarray<T> x) const;
    void fill();
    };

The class describes an object that stores a reference to an object x of class valarray <T>, along with an object ba of class valarray<bool> which describes the sequence of elements to select from the valarray<T> object.

You construct a mask_array<T> object only by writing an expression of the form x[xa]. The member functions of class mask_array then behave like the corresponding function signatures defined for valarray<T>, except that only the sequence of selected elements is affected.

The sequence consists of, at most, ba. size () elements. An element j is included only if ba[j] is true. Thus, there are as many elements in the sequence as there are true elements in ba. If i is the index of the lowest true element in ba, then x[i] is element zero in the selected sequence. For example:

const bool vb[] = {false, false, true, true, false, true};
// x[valarray<bool>(vb, 56] selects eleeents with indices
//   2, 3, 5


max

template<class T>
    T max(const valarray<T>& x);

The template function returns the value of the largest element of x, by applying operator< between pairs of elements of class T.

Microsoft-Specific:
To avoid conflicts with min and max in WINDEF.H, use _MIN and _MAX instead. These macros evaluate to _cpp_min and _cpp_max, respectively.
END Microsoft-Specific


min

template<class T>
    T min(const valarray<T>& x);

The template function returns the value of the smallest element of x, by applying operator< between pairs of elements of class T.

Microsoft-Specific:
To avoid conflicts with min and max in WINDEF.H, use _MIN and _MAX instead. These macros evaluate to _cpp_min and _cpp_max, respectively.
END Microsoft-Specific


operator!=

template<class T>
    valarray<bool> operator!=(const valarray<T>& x,
        const valarray<T>& y);
template<class T>
    valarray<bool> operator!=(const valarray<T> x, const T& y);
template<class T>
    valarray<bool> operator!=(const T& x, const valarray<T>& y);

The first template operator returns an object of class valarray<bool>, each of whose elements I is x[I] != y[I]. The second template operator stores in element I x[I] != y. The third template operator stores in element I x != y[I].


operator%

template<class T>
    valarray<T> operator%(const valarray<T>& lhs,
        const valarray<T>& rhs);
template<class T>
    valarray<T> operator%(const valarray<T> lhs, const T& rhs);
template<class T>
    valarray<T> operator%(const T& lhs, const valarray<T>& rhs);

The first template operator returns an object of class valarray <T>, each of whose elements I is x[I] % y[I]. The second template operator stores in element I x[I] % y. The third template operator stores in element I x % y[I].


operator&

template<class T>
    valarray<T> operator&(const valarray<T>& lhs,
        const valarray<T>& rhs);
template<class T>
    valarray<T> operator&(const valarray<T> lhs, const T& rhs);
template<class T>
    valarray<T> operator&(const T& lhs, const valarray<T>& rhs);

The first template operator returns an object of class valarray <T>, each of whose elements I is x[I] & y[I]. The second template operator stores in element I x[I] & y. The third template operator stores in element I x & y[I].


operator&&

template<class T>
    valarray<bool> operator&&(const valarray<T>& lhs,
        const valarray<T>& rhs);
template<class T>
    valarray<bool> operator&&(const valarray<T> lhs, const T& rhs);
template<class T>
    valarray<bool> operator&&(const T& lhs, const valarray<T>& rhs);

The first template operator returns an object of class valarray <bool>, each of whose elements I is x[I] && y[I]. The second template operator stores in element I x[I] && y. The third template operator stores in element I x && y[I].


operator>

template<class T>
    valarray<bool> operator>(const valarray<T>& x,
        const valarray<T>& y);
template<class T>
    valarray<bool> operator>(const valarray<T> x, const T& y);
template<class T>
    valarray<bool> operator>(const T& x, const valarray<T>& y);

The first template operator returns an object of class valarray<bool>, each of whose elements I is x[I] > y[I]. The second template operator stores in element I x[I] > y. The third template operator stores in element I x > y[I].


operator>>

template<class T>
    valarray<T> operator>>(const valarray<T>& lhs,
        const valarray<T>& rhs);
template<class T>
    valarray<T> operator>>(const valarray<T> lhs, const T& rhs);
template<class T>
    valarray<T> operator>>(const T& lhs, const valarray<T>& rhs);

The first template operator returns an object of class valarray <T>, each of whose elements I is x[I] >> y[I]. The second template operator stores in element I x[I] >> y. The third template operator stores in element I x >> y[I].


operator>=

template<class T>
    valarray<bool> operator>=(const valarray<T>& x,
        const valarray<T>& y);
template<class T>
    valarray<bool> operator>=(const valarray<T> x, const T& y);
template<class T>
    valarray<bool> operator>=(const T& x, const valarray<T>& y);

The first template operator returns an object of class valarray<bool>, each of whose elements I is x[I] >= y[I]. The second template operator stores in element I x[I] >= y. The third template operator stores in element I x >= y[I].


operator<

template<class T>
    valarray<bool> operator<(const valarray<T>& x,
        const valarray<T>& y);
template<class T>
    valarray<bool> operator<(const valarray<T> x, const T& y);
template<class T>
    valarray<bool> operator<(const T& x, const valarray<T>& y);

The first template operator returns an object of class valarray<bool>, each of whose elements I is x[I] < y[I]. The second template operator stores in element I x[I] < y. The third template operator stores in element I x < y[I].


operator<<

template<class T>
    valarray<T> operator<<(const valarray<T>& lhs,
        const valarray<T>& rhs);
template<class T>
    valarray<T> operator<<(const valarray<T> lhs, const T& rhs);
template<class T>
    valarray<T> operator<<(const T& lhs, const valarray<T>& rhs);

The first template operator returns an object of class valarray <T>, each of whose elements I is x[I] << y[I]. The second template operator stores in element I x[I] << y. The third template operator stores in element I x << y[I].


operator<=

template<class T>
    valarray<bool> operator<=(const valarray<T>& x,
        const valarray<T>& y);
template<class T>
    valarray<bool> operator<=(const valarray<T> x, const T& y);
template<class T>
    valarray<bool> operator<=(const T& x, const valarray<T>& y);

The first template operator returns an object of class valarray<bool>, each of whose elements I is x[I] <= y[I]. The second template operator stores in element I x[I] <= y. The third template operator stores in element I x <= y[I].


operator*

template<class T>
    valarray<T> operator*(const valarray<T>& lhs,
        const valarray<T>& rhs);
template<class T>
    valarray<T> operator*(const valarray<T> lhs, const T& rhs);
template<class T>
    valarray<T> operator*(const T& lhs, const valarray<T>& rhs);

The first template operator returns an object of class valarray <T>, each of whose elements I is x[I] * y[I]. The second template operator stores in element I x[I] * y. The third template operator stores in element I x * y[I].


operator+

template<class T>
    valarray<T> operator+(const valarray<T>& lhs,
        const valarray<T>& rhs);
template<class T>
    valarray<T> operator+(const valarray<T> lhs, const T& rhs);
template<class T>
    valarray<T> operator+(const T& lhs, const valarray<T>& rhs);

The first template operator returns an object of class valarray <T>, each of whose elements I is x[I] + y[I]. The second template operator stores in element I x[I] + y. The third template operator stores in element I x + y[I].


operator-

template<class T>
    valarray<T> operator-(const valarray<T>& lhs,
        const valarray<T>& rhs);
template<class T>
    valarray<T> operator-(const valarray<T> lhs, const T& rhs);
template<class T>
    valarray<T> operator-(const T& lhs, const valarray<T>& rhs);

The first template operator returns an object of class valarray <T>, each of whose elements I is x[I] - y[I]. The second template operator stores in element I x[I] - y. The third template operator stores in element I x - y[I].


operator/

template<class T>
    valarray<T> operator/(const valarray<T>& lhs,
        const valarray<T>& rhs);
template<class T>
    valarray<T> operator/(const valarray<T> lhs, const T& rhs);
template<class T>
    valarray<T> operator/(const T& lhs, const valarray<T>& rhs);

The first template operator returns an object of class valarray <T>, each of whose elements I is x[I] / y[I]. The second template operator stores in element I x[I] / y. The third template operator stores in element I x / y[I].


operator==

template<class T>
    valarray<bool> operator==(const valarray<T>& x,
        const valarray<T>& y);
template<class T>
    valarray<bool> operator==(const valarray<T> x, const T& y);
template<class T>
    valarray<bool> operator==(const T& x  const valarray<T>& y);

The first template operator returns an object of class valarray<bool>, each of whose elements I is x[I] == y[I]. The second template operator stores in element I x[I] == y. The third template operator stores in element I x == y[I].


operator^

template<class T>
    valarray<T> operator^(const valarray<T>& lhs,
        const valarray<T>& rhs);
template<class T>
    valarray<T> operator^(const valarray<T> lhs, const T& rhs);
template<class T>
    valarray<T> operator^(const T& lhs, const valarray<T>& rhs);

The first template operator returns an object of class valarray <T>, each of whose elements I is x[I] ^ y[I]. The second template operator stores in element I x[I] ^ y. The third template operator stores in element I x ^ y[I].


operator|

template<class T>
    valarray<T> operator|(const valarray<T>& lhs,
        const valarray<T>& rhs);
template<class T>
    valarray<T> operator|(const valarray<T> lhs, const T& rhs);
template<class T>
    valarray<T> operator|(const T& lhs, const valarray<T>& rhs);

The first template operator returns an object of class valarray <T>, each of whose elements I is x[I] | y[I]. The second template operator stores in element I x[I] | y. The third template operator stores in element I x | y[I].


operator||

template<class T>
    valarray<bool> operator||(const valarray<T>& lhs,
        const valarray<T>& rhs);
template<class T>
    valarray<bool> operator||(const valarray<T> lhs, const T& rhs);
template<class T>
    valarray<bool> operator||(const T& lhs, const valarray<T>& rhs);

The first template operator returns an object of class valarray <bool>, each of whose elements I is x[I] || y[I]. The second template operator stores in element I x[I] || y. The third template operator stores in element I x || y[I].


pow

template<class T>
    valarray<T> pow(const valarray<T>& x,
        const valarray<T>& y);
template<class T>
    valarray<T> pow(const valarray<T> x, const T& y);
template<class T>
    valarray<T> pow(const T& x, const valarray<T>& y);

The first template function returns an object of class valarray <T>, each of whose elements I is x[I] raised to the y[I] power. The second template function stores in element I x[I] raised to the y power. The third template function stores in element I x raised to the y[I] power.

See the related sample program.


sin

template<class T>
    valarray<T> sin(const valarray<T>& x);

The template function returns an object of class valarray <T>, each of whose elements I is the sine of x[I].

See the related sample program.


sinh

template<class T>
    valarray<T> sinh(const valarray<T>& x);

The template function returns an object of class valarray <T>, each of whose elements I is the hyperbolic sine of x[I].

See the related sample program.


slice

class slice {
public:
    slice();
    slice(size_t st, size_t len, size_t str);
    size_t start() const;
    size_t size() const;
    size_t stride() const;
    };

The class stores the parameters that characterize a slice_array when an object of class slice appears as a subscript for an object of class valarray <T>. The stored values include:

  • A starting index
  • A total length
  • A stride, or distance between subsequent indices


slice::size

size_t size() const;

The member function returns the stored total length.


slice::start

size_t start() const;

The member function returns the stored starting index.


slice::slice

slice();
slice(size_t st,
        const valarray<size_t> len, const valarray<size_t> str);

The default constructor stores zeros for the starting index, total length, and stride. The second constructor stores st for the starting index, len for the total length, and str for the stride.


slice::stride

size_t stride() const;

The member function returns the stored stride.


slice_array

template<class T>
    class slice_array {
public:
    typedef T value_type;
    void operator=(const valarray<T> x) const;
    void operator=(const T& x);
    void operator*=(const valarray<T> x) const;
    void operator/=(const valarray<T> x) const;
    void operator%=(const valarray<T> x) const;
    void operator+=(const valarray<T> x) const;
    void operator-=(const valarray<T> x) const;
    void operator^=(const valarray<T> x) const;
    void operator&=(const valarray<T> x) const;
    void operator|=(const valarray<T> x) const;
    void operator<<=(const valarray<T> x) const;
    void operator>>=(const valarray<T> x) const;
    void fill();
    };

The class describes an object that stores a reference to an object x of class valarray <T>, along with an object sl of class slice which describes the sequence of elements to select from the valarray<T> object.

You construct a slice_array<T> object only by writing an expression of the form x[sl]. The member functions of class slice_array then behave like the corresponding function signatures defined for valarray<T>, except that only the sequence of selected elements is affected.

The sequence consists of sl. size () elements, where element i becomes the index sl. start () + i * sl. stride () within x. For example:

// x[slice(2, 5, 3)] selects elements with indices
//   2, 5, 8, 11, 14


sqrt

template<class T>
    valarray<T> sqrt(const valarray<T>& x);

The template function returns an object of class valarray <T>, each of whose elements I is the square root of x[I].

See the related sample program.


tan

template<class T>
    valarray<T> tan(const valarray<T>& x);

The template function returns an object of class valarray <T>, each of whose elements I is the tangent of x[I].

See the related sample program.


tanh

template<class T>
    valarray<T> tanh(const valarray<T>& x);

The template function returns an object of class valarray <T>, each of whose elements I is the hyperbolic tangent of x[I].

See the related sample program.


valarray

apply  ·  cshift  ·  fill  ·  free  ·  max<
/b>  ·  min  ·  operator T *  ·  operator!  ·  operator%=  ·
 operator&=  ·  operator>>=  ·  operator<<=  ·  operato
r*=  ·  operator+  ·  operator+=  ·  operator-
·  operator-=  ·  operator/=  ·  operator=  ·  operator[]  ·
 operator^=  ·  operator|=  ·  operator~
·  resize  ·  shift  ·  size  ·  sum  ·  valarray  ·  value_type

template<class T>
    class valarray {
public:
    typedef T value_type;
    valarray();
    explicit valarray(size_t n);
    valarray(const T& val, size_t n));
    valarray(const T *p, size_t n);
    valarray(const slice_array<T>& sa);
    valarray(const gslice_array<T>& ga);
    valarray(const mask_array<T>& ma);
    valarray(const indirect_array<T>& ia);
    valarray<T>& operator=(const valarray<T>& va);
    valarray<T>& operator=(const T& x);
    valarray<T>& operator=(const slice_array<T>& sa);
    valarray<T>& operator=(const gslice_array<T>& ga);
    valarray<T>& operator=(const mask_array<T>& ma);
    valarray<T>& operator=(const indirect_array<T>& ia);
    T operator[](size_t n) const;
    T& operator[](size_t n);
    valarray<T> operator[](slice sa) const;
    slice_array<T> operator[](slice sa);
    valarray<T> operator[](const gslice& ga) const;
    gslice_array<T> operator[](const gslice& ga);
    valarray<T> operator[](const valarray<bool>& ba) const;
    mask_array<T> operator[](const valarray<bool>& ba);
    valarray<T> operator[](const valarray<size_t>& xa) const;
    indirect_array<T> operator[](const valarray<size_t>& xa);
    valarray<T> operator+();
    valarray<T> operator-();
    valarray<T> operator~();
    valarray<bool> operator!();
    valarray<T>& operator*=(const valarray<T>& x);
    valarray<T>& operator*=(const T& x);
    valarray<T>& operator/=(const valarray<T>& x);
    valarray<T>& operator/=(const T& x);
    valarray<T>& operator%=(const valarray<T>& x);
    valarray<T>& operator%=(const T& x);
    valarray<T>& operator+=(const valarray<T>& x);
    valarray<T>& operator+=(const T& x);
    valarray<T>& operator-=(const valarray<T>& x);
    valarray<T>& operator-=(const T& x);
    valarray<T>& operator^=(const valarray<T>& x);
    valarray<T>& operator^=(const T& x);
    valarray<T>& operator&=(const valarray<T>& x);
    valarray<T>& operator&=(const T& x);
    valarray<T>& operator|=(const valarray<T>& x);
    valarray<T>& operator|=(const T& x);
    valarray<T>& operator<<=(const valarray<T>& x);
    valarray<T>& operator<<=(const T& x);
    valarray<T>& operator>>=(const valarray<T>& x);
    valarray<T>& operator>>=(const T& x);
    size_t size() const;
    T sum() const;
    T max() const;
    T min() const;
    valarray<T> shift(int n) const;
    valarray<T> cshift(int n) const;
    valarray<T> apply(T fn(T)) const;
    valarray<T> apply(T fn(const T&)) const;
    void fill(const T& val);
    void free();
    void resize(size_t n, const T& c = T());
    };

The template class describes an object that controls a varying-length sequence of elements of type T. The sequence is stored as an array of T. It differs from template class vector in two important ways:

  • It defines numerous arithmetic operations between corresponding elements of valarray<T> objects of the same type and length, such as x = cos(y) + sin(z).
  • It defines a variety of interesting ways to subscript a valarray<T> object, by overloading operator[].


valarray::apply

valarray<T> apply(T fn(T)) const;
valarray<T> apply(T fn(const T&)) const;

The member function returns an object of class valarray <T>, of length size (), each of whose elements I is fn((*this)[I]).


valarray::cshift

valarray<T> cshift(int n) const;

The member function returns an object of class valarray <T>, of length size (), each of whose elements I is (*this)[(I + n) % size()]. Thus, if element zero is taken as the leftmost element, a positive value of n shifts the elements circularly left n places.


valarray::fill

void fill(const T& val);

The member function stores val in every element of *this.


valarray::free

void free();

The member function destroys all elements of *this, leaving an array of zero length.


valarray::max

T max() const;

The member function returns the value of the largest element of *this, which must have nonzero length. If the length is greater than one, it compares values by applying operator< between pairs of corresponding elements of class T.


valarray::min

T min() const;

The member function returns the value of the smallest element of *this, which must have nonzero length. If the length is greater than one, it compares values by applying operator< between pairs of elements of class T.


valarray::operator!

valarray<bool> operator!();

The member operator returns an object of class valarray <bool>, of length size (), each of whose elements I is !(*this).


valarray::operator%=

valarray<T>& operator%=(const valarray<T>& x);
valarray<T>& operator%=(const T& x);

The member operator replaces each element I of *this with (*this)[I] % x[I]. It returns *this.


valarray::operator&=

valarray<T>& operator&=(const valarray<T>& x);
valarray<T>& operator&=(const T& x);

The member operator replaces each element I of *this with (*this)[I] & x[I]. It returns *this.


valarray::operator>>=

valarray<T>& operator>>=(const valarray<T>& x);
valarray<T>& operator>>=(const T& x);

The member operator replaces each element I of *this with (*this)[I] >> x[I]. It returns *this.


valarray::operator<<=

valarray<T>& operator<<=(const valarray<T>& x);
valarray<T>& operator<<=(const T& x);

The member operator replaces each element I of *this with (*this)[I] << x[I]. It returns *this.


valarray::operator*=

valarray<T>& operator*=(const valarray<T>& x);
valarray<T>& operator*=(const T& x);

The member operator replaces each element I of *this with (*this)[I] * x[I]. It returns *this.


valarray::operator+

valarray<T> operator+();

The member operator returns an object of class valarray <T>, of length size (), each of whose elements I is (*this)[I].


valarray::operator+=

valarray<T>& operator+=(const valarray<T>& x);
valarray<T>& operator+=(const T& x);

The member operator replaces each element I of *this with (*this)[I] + x[I]. It returns *this.


valarray::operator-

valarray<T> operator-();

The member operator returns an object of class valarray <T>, of length size (), each of whose elements I is -(*this)[I].


valarray::operator-=

valarray<T>& operator-=(const valarray<T>& x);
valarray<T>& operator-=(const T& x);

The member operator replaces each element I of *this with (*this)[I] - x[I]. It returns *this.


valarray::operator/=

valarray<T>& operator/=(const valarray<T>& x);
valarray<T>& operator/=(const T& x);

The member operator replaces each element I of *this with (*this)[I] / x[I]. It returns *this.


valarray::operator=

valarray<T>& operator=(const valarray<T>& va);
    valarray<T>& operator=(const T& x);
valarray<T>& operator=(const slice_array<T>& sa);
valarray<T>& operator=(const gslice_array<T>& ga);
valarray<T>& operator=(const mask_array<T>& ma);
valarray<T>& operator=(const indirect_array<T>& ia);

The first member operator replaces the controlled sequence with a copy of the sequence controlled by va. The second member operator replaces each element of the controlled sequence with a copy of x. The remaining member operators replace those elements of the controlled sequence selected by their arguments, which are generated only by operator[]. If the value of a member in the replacement controlled sequence depends on a member in the initial controlled sequence, the result is undefined.

If the length of the controlled sequence changes, the result is generally undefined. In this implementation, however, the effect is merely to invalidate any pointers or references to elements in the controlled sequence.


valarray::operator[]

T& operator[](size_t n);
slice_array<T> operator[](slice sa);
gslice_array<T> operator[](const gslice& ga);
mask_array<T> operator[](const valarray<bool>& ba);
indirect_array<T> operator[](const valarray<size_t>& xa);

T operator[](size_t n) const;
valarray<T> operator[](slice sa) const;
valarray<T> operator[](const gslice& ga) const;
valarray<T> operator[](const valarray<bool>& ba) const;
valarray<T> operator[](const valarray<size_t>& xa) const;

The member operator is overloaded to provide several ways to select sequences of elements from among those controlled by *this. The first group of five member operators works in conjunction with various overloads of operator= (and other assigning operators) to allow selective replacement (slicing) of the controlled sequence. The selected elements must exist.

The first member operator selects element n. For example:

valarray<char> v0("abcdefghijklmnop", 16);
v0[3] = 'A';
// v0 == valarray<char>("abcAefghijklmnop", 16)

The second member operator selects those elements of the controlled sequence designated by sa. For example:

valarray<char> v0("abcdefghijklmnop", 16);
valarray<char> v1("ABCDE", 5);
v0[slice(2, 5, 3)] = v1;
// v0 == valarray<char>("abAdeBghCjkDmnEp", 16)

The third member operator selects those elements of the controlled sequence designated by ga. For example:

valarray<char> v0("abcdefghijklmnop", 16);
valarray<char> v1("ABCDEF", 6);
const size_t lv[] = {2, 3};
const size_t dv[] = {7, 2};
const valarray<size_t> len(lv, 2), str(dv, 2);
v0[gslice(3, len, str)] = v1;
// v0 == valarray<char>("abcAeBgCijDlEnFp", 16)

The fourth member operator selects those elements of the controlled sequence designated by ma. For example:

valarray<char> v0("abcdefghijklmnop", 16);
valarray<char> v1("ABC", 3);
const bool vb[] = {false, false, true, true, false, true};
v0[valarray<bool>(vb, 6)] = v1;
// v0 == valarray<char>("abABeCghijklmnop", 16)

The fifth member operator selects those elements of the controlled sequence designated by ia. For example:

valarray<char> v0("abcdefghijklmnop", 16);
valarray<char> v1("ABCDE", 5);
const size_t vi[] = {7, 5, 2, 3, 8};
v0[valarray<size_t>(vi, 5)] = v1;
// v0 == valarray<char>("abCDeBgAEjklmnop", 16)

In the second group, each of the five member operators constructs an object that represents the value(s) selected. The selected elements must exist.

The sixth member operator returns the value of element n. For example:

valarray<char> v0("abcdefghijklmnop", 16);
// v0[3] returns 'd'

The seventh member operator returns an object of class valarray<T> containing those elements of the controlled sequence designated by sa. For example:

valarray<char> v0("abcdefghijklmnop", 16);
// v0[slice(2, 5, 3)] returns valarray<char>("cfilo", 5)

The eighth member operator selects those elements of the controlled sequence designated by ga. For example:

valarray<char> v0("abcdefghijklmnop", 16);
const size_t lv[] = {2, 3};
const size_t dv[] = {7, 2};
const valarray<size_t> len(lv, 2), str(dv, 2);
// v0[gslice(3, len, str)] returns valarray<char>("dfhkmo", 6)

The ninth member operator selects those elements of the controlled sequence designated by ma. For example:

valarray<char> v0("abcdefghijklmnop", 16);
const bool vb[] = {false, false, true, true, false, true};
// v0[valarray<bool>(vb, 6)] returns valarray<char>("cdf", 3)

The last member operator selects those elements of the controlled sequence designated by ia. For example:

valarray<char> v0("abcdefghijklmnop", 16);
const size_t vi[] = {7, 5, 2, 3, 8};
// v0[valarray<size_t>(vi, 5)] returns valarray<char>("hfcdi", 3)


valarray::operator^=

valarray<T>& operator^=(const valarray<T>& x);
valarray<T>& operator^=(const T& x);

The member operator replaces each element I of *this with (*this)[I] ^ x[I]. It returns *this.


valarray::operator|=

valarray<T>& operator|=(const valarray<T>& x);
valarray<T>& operator|=(const T& x);

The member operator replaces each element I of *this with (*this)[I] | x[I]. It returns *this.


valarray::operator~

valarray<T> operator~();

The member operator returns an object of class valarray <T>, of length size (), each of whose elements I is ~(*this)[I].


valarray::resize

void resize(size_t n, const T& c = T());

The member function ensures that size () henceforth returns n. If it must lengthen the controlled sequence, it appends elements with value c. Any pointers or references to elements in the controlled sequence are invalidated.


valarray::shift

valarray<T> shift(int n) const;

The member function returns an object of class valarray <T>, of length size (), each of whose elements I is either (*this)[I + n], if I + n is a valid subscript, or T(). Thus, if element zero is taken as the leftmost element, a positive value of n shifts the elements left n places, with zero fill.


valarray::size

size_t size() const;

The member function returns the number of elements in the array.


valarray::sum

T sum() const;

The member function returns the sum of all elements of *this, which must have nonzero length. If the length is greater than one, it adds values to the sum by applying operator+= between pairs of elements of class T.


valarray::valarray

valarray();
explicit valarray(size_t n);
valarray(const T& val, size_t n));
valarray(const T *p, size_t n);
valarray(const slice_array<T>& sa);
valarray(const gslice_array<T>& ga);
valarray(const mask_array<T>& ma);
valarray(const indirect_array<T>& ia);

The first (default) constructor initializes the object to an empty array. Each of the next three constructors initializes the object to an array of n elements as follows:

  • For explicit valarray(size_t n), each element is initialized with the default constructor.
  • For valarray(const T& val, size_t n)), each element is initialized with val.
  • For valarray(const T *p, size_t n), the element at position I is initialized with p[I].

Each of the remaining constructors initializes the object to a valarray<T> object determined by the argument.


valarray::value_type

typedef T value_type;

The type is a synonym for the template parameter T.


valarray<bool>

class valarray<bool>

The type is a specialization of template class valarray, for elements of type bool.


 <vector>

<vector>

namespace std {
template<class T, class A>
    class vector;
template<class A>
    class vector<bool, A>;
//    TEMPLATE FUNCTIONS
template<class T, class A>
    bool operator==(
        const vector<T, A>& lhs,
        const vector<T, A>& rhs);
template<class T, class A>
    bool operator!=(
        const vector<T, A>& lhs,
        const vector<T, A>& rhs);
template<class T, class A>
    bool operator<(
        const vector<T, A>& lhs,
        const vector<T, A>& rhs);
template<class T, class A>
    bool operator>(
        const vector<T, A>& lhs,
        const vector<T, A>& rhs);
template<class T, class A>
    bool operator<=(
        const vector<T, A>& lhs,
        const vector<T, A>& rhs);
template<class T, class A>
    bool operator>=(
        const vector<T, A>& lhs,
        const vector<T, A>& rhs);
template<class T, class A>
    void swap(
        const vector<T, A>& lhs,
        const vector<T, A>& rhs);
    };

Include the STL standard header <vector> to define the container template class vector and three supporting templates.


operator!=

template<class T, class A>
    bool operator!=(
        const vector <T, A>& lhs,
        const vector <T, A>& rhs);

The template function returns !(lhs == rhs).


operator==

template<class T, class A>
    bool operator==(
        const vector <T, A>& lhs,
        const vector <T, A>& rhs);

The template function overloads operator== to compare two objects of template class vector. The function returns lhs. size () == rhs.size() && equal (lhs. begin (), lhs. end (), rhs.begin()).

See the related sample program.


operator<

template<class T, class A>
    bool operator<(
        const vector <T, A>& lhs,
        const vector <T, A>& rhs);

The template function overloads operator< to compare two objects of template class vector. The function returns lexicographical_compare (lhs. begin (), lhs. end (), rhs.begin(), rhs.end()).

See the related sample program.


operator<=

template<class T, class A>
    bool operator<=(
        const vector <T, A>& lhs,
        const vector <T, A>& rhs);

The template function returns !(rhs < lhs).


operator>

template<class T, class A>
    bool operator>(
        const vector <T, A>& lhs,
        const vector <T, A>& rhs);

The template function returns rhs < lhs.


operator>=

template<class T, class A>
    bool operator>=(
        const vector <T, A>& lhs,
        const vector <T, A>& rhs);

The template function returns !(lhs < rhs).


swap

template<class T, class A>
    void swap(
        const vector <T, A>& lhs,
        const vector <T, A>& rhs);

The template function executes lhs. swap (rhs).


vector

allocator_type · assign · at · back · begin · capacity · clear · const_iterator · const_reference · const_reverse_iterator · difference_type · empty · end · erase · front · get_allocator · insert · iterator · max_size · operator[] · pop_back · push_back · rbegin · reference · rend · reserve · resize · reverse_iterator · size · size_type · swap · value_type · vector

template<class T, class A = allocator<T> >
    class vector {
public:
    typedef A allocator_type;
    typedef A::size_type size_type;
    typedef A::difference_type difference_type;
    typedef A::reference reference;
    typedef A::const_reference const_reference;
    typedef A::value_type value_type;
    typedef T0 iterator;
    typedef T1 const_iterator;
    typedef reverse_iterator<iterator, value_type,
        reference, A::pointer, difference_type>
            reverse_iterator;
    typedef reverse_iterator<const_iterator, value_type,
        const_reference, A::const_pointer, difference_type>
            const_reverse_iterator;
    explicit vector(const A& al = A());
    explicit vector(size_type n, const T& v = T(), const A& al = A());
    vector(const vector& x);
    vector(const_iterator first, const_iterator last,
        const A& al = A());
    void reserve(size_type n);
    size_type capacity() const;
    iterator begin();
    const_iterator begin() const;
    iterator end();
    iterator end() const;
    reverse_iterator rbegin();
    const_reverse_iterator rbegin() const;
    reverse_iterator rend();
    const_reverse_iterator rend() const;
    void resize(size_type n, T x = T());
    size_type size() const;
    size_type max_size() const;
    bool empty() const;
    A get_allocator() const;
    reference at(size_type pos);
    const_reference at(size_type pos) const;
    reference operator[](size_type pos);
    const_reference operator[](size_type pos);
    reference front();
    const_reference front() const;
    reference back();
    const_reference back() const;
    void push_back(const T& x);
    void pop_back();
    void assign(const_iterator first, const_iterator last);
    void assign(size_type n, const T& x = T());
    iterator insert(iterator it, const T& x = T());
    void insert(iterator it, size_type n, const T& x);
    void insert(iterator it,
        const_iterator first, const_iterator last);
    iterator erase(iterator it);
    iterator erase(iterator first, iterator last);
    void clear();
    void swap(vector x);
protected:
    A allocator;
    };

The template class describes an object that controls a varying-length sequence of elements of type T. The sequence is stored as an array of T.

The object allocates and frees storage for the sequence it controls through a protected object named allocator, of class A. Such an allocator object must have the same external interface as an object of template class allocator. Note that allocator is not copied when the object is assigned.

Vector reallocation occurs when a member function must grow the controlled sequence beyond its current storage capacity. Other insertions and erasures may alter various storage addresses within the sequence. In all such cases, iterators or references that point at altered portions of the controlled sequence become invalid.


vector::allocator_type

typedef A allocator_type;

The type is a synonym for the template parameter A.


vector::assign

void assign(const_iterator first, const_iterator last);
void assign(size_type n, const T& x = T());

The first member function replaces the sequence controlled by *this with the sequence [first, last). The second member function replaces the sequence controlled by *this with a repetition of n elements of value x.

In this implementation, if a translator does not support member template functions, the templates:

template<class InIt>
    void assign(InIt first, InIt last);
template<class Size, class T2>
    void assign(Size n, const T2& x = T2());

are replaced by:

void assign(const_iterator first, const_iterator last);
void assign(size_type n, const T& x = T());


vector::at

const_reference at(size_type pos) const;
reference at(size_type pos);

The member function returns a reference to the element of the controlled sequence at position pos. If that position is invalid, the function throws an object of class out_of_range.


vector::back

reference back();
const_reference back() const;

The member function returns a reference to the last element of the controlled sequence, which must be non-empty.

See the related sample program.


vector::begin

const_iterator begin() const;
iterator begin();

The member function returns a random-access iterator that points at the first element of the sequence (or just beyond the end of an empty sequence).


vector::capacity

size_type capacity() const;

The member function returns the storage currently allocated to hold the controlled sequence, a value at least as large as size ().

See the related sample program.


vector::clear

void clear() const;

The member function calls erase ( begin (), end ()).


vector::const_iterator

typedef T1 const_iterator;

The type describes an object that can serve as a constant random-access iterator for the controlled sequence. It is described here as a synonym for the unspecified type T1.


vector::const_reference

typedef A::const_reference const_reference;

The type describes an object that can serve as a constant reference to an element of the controlled sequence.


vector::const_reverse_iterator

typedef reverse_iterator<const_iterator, value_type,
    const_reference, A::const_pointer, difference_type>
        const_reverse_iterator;

The type describes an object that can serve as a constant reverse iterator for the controlled sequence.


vector::difference_type

typedef A::difference_type difference_type;

The signed integer type describes an object that can represent the difference between the addresses of any two elements in the controlled sequence.


vector::empty

bool empty() const;

The member function returns true for an empty controlled sequence.

See the related sample program.


vector::end

const_iterator end() const;
iterator end();

The member function returns a random-access iterator that points just beyond the end of the sequence.


vector::erase

iterator erase(iterator it);
iterator erase(iterator first, iterator last);

The first member function removes the element of the controlled sequence pointed to by it. The second member function removes the elements of the controlled sequence in the range [first, last). Both return an iterator that designates the first element remaining beyond any elements removed, or end () if no such element exists.

Erasing N elements causes N destructor calls and an assignment for each of the elements between the insertion point and the end of the sequence. No reallocation occurs, so iterators and references become invalid only from the first element erased through the end of the sequence.

See the related sample program.


vector::front

reference front();
const_reference front() const;

The member function returns a reference to the first element of the controlled sequence, which must be non-empty.

See the related sample program.


vector::get_allocator

A get_allocator() const;

The member function returns allocator.


vector::insert

iterator insert(iterator it, const T& x = T());
void insert(iterator it, size_type n, const T& x);
void insert(iterator it,
    const_iterator first, const_iterator last);

Each of the member functions inserts, before the element pointed to by it in the controlled sequence, a sequence specified by the remaining operands. The first member function inserts a single element with value x and returns an iterator that points to the newly inserted element. The second member function inserts a repetition of n elements of value x. The last member function inserts the sequence [first, last).

In this implementation, if a translator does not support member template functions, the template:

template<class InIt>
    void insert(iterator it, InIt first, InIt last);

is replaced by:

void insert(iterator it,
    const_iterator first, const_iterator last);

When inserting a single element, the number of element copies is linear in the number of elements between the insertion point and the end of the sequence. When inserting a single element at the end of the sequence, the amortized number of element copies is constant. When inserting N elements, the number of element copies is linear in N plus the number of elements between the insertion point and the end of the sequence -- except when the template member is specialized for InIt, an input iterator which behaves like N single insertions.

If reallocation occurs, the size of the controlled sequence at least doubles, and all iterators and references become invalid. If no reallocation occurs, iterators become invalid only from the point of insertion through the end of the sequence.


vector::iterator

typedef T0 iterator;

The type describes an object that can serve as a random-access iterator for the controlled sequence. It is described here as a synonym for the unspecified type T0.


vector::max_size

size_type max_size() const;

The member function returns the length of the longest sequence that the object can control.

See the related sample program.


vector::operator[]

const_reference operator[](size_type pos) const;
reference operator[](size_type pos);

The member function returns a reference to the element of the controlled sequence at position pos. If that position is invalid, the behavior is undefined.


vector::pop_back

void pop_back();

The member function removes the last element of the controlled sequence, which must be non-empty.

See the related sample program.


vector::push_back

void push_back(const T& x);

The member function inserts an element with value x at the end of the controlled sequence.

See the related sample program.


vector::rbegin

const_reverse_iterator rbegin() const;
reverse_iterator rbegin();

The member function returns a reverse iterator that points just beyond the end of the controlled sequence. Hence, it designates the beginning of the reverse sequence.


vector::reference

typedef A::reference reference;

The type describes an object that can serve as a reference to an element of the controlled sequence.


vector::rend

const_reverse_iterator rend() const;
reverse_iterator rend();

The member function returns a reverse iterator that points at the first element of the sequence (or just beyond the end of an empty sequence). Hence, it designates the end of the reverse sequence.


vector::reserve

void reserve(size_type n);

The member function ensures that capacity () henceforth returns at least n.

See the related sample program.


vector::resize

void resize(size_type n, T x = T());

The member function ensures that size () henceforth returns n. If it must lengthen the controlled sequence, it appends elements with value x.

See the related sample program.


vector::reverse_iterator

typedef reverse_iterator<iterator, value_type,
    reference, A::pointer, difference_type>
        reverse_iterator;

The type describes an object that can serve as a reverse iterator for the controlled sequence.


vector::size

size_type size() const;

The member function returns the length of the controlled sequence.

See the related sample program.


vector::size_type

typedef A::size_type size_type;

The unsigned integer type describes an object that can represent the length of any controlled sequence.


vector::swap

void swap(vector& str);

The member function swaps the controlled sequences between *this and str. If allocator == str.allocator, it does so in constant time. Otherwise, it performs a number of element assignments and constructor calls proportional to the number of elements in the two controlled sequences.


vector::value_type

typedef A::value_type value_type;

The type is a synonym for the template parameter T.


vector::vector

explicit vector(const A& al = A());
explicit vector(size_type n, const T& v = T(), const A& al = A());
vector(const vector& x);
vector(const_iterator first, const_iterator last,
    const A& al = A());

All constructors store the allocator object al (or, for the copy constructor, x. get_allocator ()) in allocator and initialize the controlled sequence. The first constructor specifies an empty initial controlled sequence. The second constructor specifies a repetition of n elements of value x. The third constructor specifies a copy of the sequence controlled by x. The last constructor specifies the sequence [first, last).

In this implementation, if a translator does not support member template functions, the template:

template<class InIt>
    vector(InIt first, InIt last, const A& al = A());

is replaced by:

vector(const_iterator first, const_iterator last,
    const A& al = A());

All constructors copy N elements and perform no interim reallocation.


vector<bool, A>

class vector<bool, allocator<bool> > { typedef allocator<bool> A; public: class reference; typedef bool
const_reference; typedef T0 iterator; typedef T1 const_iterator; void flip(); static void swap(reference x,
reference y); // rest same as template class vector };

The class is a specialization of template class vector for elements of type bool. It alters the definition of four member types (to optimize the packing and unpacking of elements) and adds two member functions. Its behavior is otherwise the same as for template class vector.

In this implementation, if partial specializations are not supported or if bool is not a distinct type, the class should be referred to by the synonym _Bvector.


vector<bool, A>::const_iterator

typedef T1 const_iterator;

The type describes an object that can serve as a constant random-access iterator for the controlled sequence. It is described here as a synonym for the unspecified type T1.


vector<bool, A>::const_reference

typedef bool const_reference;

The type describes an object that can serve as a constant reference to an element of the controlled sequence, in this case bool.


vector<bool, A>::flip

void flip();

The member function inverts the values of all the members of the controlled sequence.


vector<bool, A>::iterator

typedef T0 iterator;

The type describes an object that can serve as a random-access iterator for the controlled sequence. It is described here as a synonym for the unspecified type T0.


vector<bool, A>::reference

class reference {
public:
    reference& operator=(const reference& x);
    reference& operator=(bool x);
    void flip();
    bool operator~() const;
    operator bool() const;
    };

The type describes an object that can serve as a reference to an element of the controlled sequence. Specifically, for two objects x and y of class reference:

  • bool(x) yields the value of the element designated by x
  • ~x yields the inverted value of the element designated by x
  • x.flip() inverts the value stored in x
  • y = bool(x) and y = x both assign the value of the element designated by x to the element designated by y

It is unspecified how member functions of class vector<bool, A> construct objects of class reference that designate elements of a controlled sequence. The default constructor for class reference generates an object that refers to no such element.


vector<bool, A>::swap

void swap(reference x, reference y);

The static member function swaps the members of the controlled sequences designated by x and y.


 <iso646.h>

<iso646.h> [Added with Amendment 1]

#define and && [keyword in C++]
#define and_eq &= [keyword in C++]
#define bitand & [keyword in C++]
#define bitor | [keyword in C++]
#define compl ~ [keyword in C++]
#define not ! [keyword in C++]
#define not_eq != [keyword in C++]
#define or || [keyword in C++]
#define or_eq |= [keyword in C++]
#define xor ^ [keyword in C++]
#define xor_eq ^= [keyword in C++]

Include the standard header <iso646.h> to provide readable alternatives to certain operators or punctuators. The standard header <iso646.h> is available even in a freestanding implementation.


and

#define and && [keyword in C++]

The macro yields the operator &&.


and_eq

#define and_eq &= [keyword in C++]

The macro yields the operator &=.


bitand

#define bitand & [keyword in C++]

The macro yields the operator &.


bitor

#define bitor | [keyword in C++]

The macro yields the operator |.


compl

#define compl ~ [keyword in C++]

The macro yields the operator ~.


not

#define not ! [keyword in C++]

The macro yields the operator !.


not_eq

#define not_eq != [keyword in C++]

The macro yields the operator !=.


or

#define or || [keyword in C++]

The macro yields the operator ||.


or_eq

#define or_eq |= [keyword in C++]

The macro yields the operator |=.


xor

#define xor ^ [keyword in C++]

The macro yields the operator ^.


xor_eq

#define xor_eq ^= [keyword in C++]

The macro yields the operator ^=.


<wchar.h>

<wchar.h> [Added with Amendment 1]

Most of the functions, types, and constants listed below are documented in the Run-Time Library Reference, a section of the Visual C++ Programmer's Guide. Those that are not documented there are relatively new to wchar.h and are documented in the topics following this one.

#define  NULL  <either 0, 0L, or (void *)0> [0 in C++]
#define  WCHAR_MAX  <#if expression >= 127>
#define  WCHAR_MIN  <#if expression <= 0>
#define  WEOF  <wint_t constant expression>
wint_t  btowc (int c);
wint_t  fgetwc (FILE *stream);
wchar_t * fgetws (wchar_t *s, int n, FILE *stream);
wint_t  fputwc (wchar_t c, FILE *stream);
int  fputws (const wchar_t *s, FILE *stream);
int  fwide (FILE *stream, int mode);
int  fwprintf (FILE *stream, const wchar_t *format, ...);
int  fwscanf (FILE *stream, const wchar_t *format, ...);
wint_t  getwc (FILE *stream);
wint_t  getwchar (void);
size_t  mbrlen (const char *s, size_t n, mbstate_t *ps);
size_t  mbrtowc (wchar_t *pwc, const char *s, size_t n, mbstate_t *ps);
int  mbsinit (const mbstate_t *ps);
size_t  mbsrtowcs (wchar_t *dst, const char **src, size_t len, mbstate_t *ps);
typedef o-type  mbstate_t ;
wint_t  putwc (wchar_t c, FILE *stream);
wint_t  putwchar (wchar_t c);
typedef ui-type  size_t ;
int  swprintf (wchar_t *s, size_t n, const wchar_t *format, ...);
int  swscanf (const wchar_t *s, const wchar_t *format, ...);
struct  tm ;
wint_t  ungetwc (wint_t c, FILE *stream);
int  vfwprintf (FILE *stream, const wchar_t *format, va_list arg);
int  vswprintf (wchar_t *s, size_t n, const wchar_t *format, va_list arg);
int  vwprintf (const wchar_t *format, va_list arg);
typedef i-type  wchar_t ; [keyword in C++]
size_t  wcrtomb (char *s, wchar_t wc, mbstate_t *ps);
wchar_t * wcscat (wchar_t *s1, const wchar_t *s2);
wchar_t * wcschr (const wchar_t *s, wchar_t c);
int  wcscmp (const wchar_t *s1, const wchar_t *s2);
int  wcscoll (const wchar_t *s1, const wchar_t *s2);
wchar_t * wcscpy (wchar_t *s1, const wchar_t *s2);
size_t  wcscspn (const wchar_t *s1, const wchar_t *s2);
size_t  wcsftime (wchar_t *s, size_t maxsize, const wchar_t *format, const struct tm
*timeptr);
size_t  wcslen (const wchar_t *s);
wchar_t * wcsncat (wchar_t *s1, const wchar_t *s2, size_t n);
int  wcsncmp (const wchar_t *s1, const wchar_t *s2, size_t n);
wchar_t * wcsncpy (wchar_t *s1, const wchar_t *s2, size_t n);
wchar_t * wcspbrk (const wchar_t *s1, const wchar_t *s2);
wchar_t * wcsrchr (const wchar_t *s, wchar_t c);
size_t  wcsrtombs (char *dst, const wchar_t **src, size_t len, mbstate_t *ps);
size_t  wcsspn (const wchar_t *s1, const wchar_t *s2);
wchar_t * wcsstr (const wchar_t *s1, const wchar_t *s2);
double  wcstod (const wchar_t *nptr, wchar_t **endptr);
wchar_t * wcstok (wchar_t *s1, const wchar_t *s2, wchar_t **ptr);
long  wcstol (const wchar_t *nptr, wchar_t **endptr, int base);
unsigned long  wcstoul (const wchar_t *nptr, wchar_t **endptr, int base);
size_t  wcsxfrm (wchar_t *s1, const wchar_t *s2, size_t n);
int  wctob (wint_t c);
typedef i_type  wint_t ;
wchar_t * wmemchr (const wchar_t *s, wchar_t c, size_t n); [not in C++]
const wchar_t * wmemchr (const wchar_t *s, wchar_t c, size_t n); [C++ only]
wchar_t * wmemchr (wchar_t *s, wchar_t c, size_t n); [C++ only]
int  wmemcmp (const wchar_t *s1, const wchar_t *s2, size_t n);
wchar_t * wmemcpy (wchar_t *s1, const wchar_t *s2, size_t n);
wchar_t * wmemmove (wchar_t *s1, const wchar_t *s2, size_t n);
wchar_t * wmemset (wchar_t *s, wchar_t c, size_t n);
int  wprintf (const wchar_t *format, ...);
int  wscanf (const wchar_t *format, ...);

Include the standard header <wchar.h> so that you can perform input and output operations on wide streams or manipulate wide strings.


WCHAR_MAX

#define WCHAR_MAX <#if expression >= 127>

The macro yields the maximum value for type wchar_t.


WCHAR_MIN

#define WCHAR_MIN <#if expression <= 0>

The macro yields the minimum value for type wchar_t.


btowc

wint_t btowc(int c);

The function returns WEOF if c equals EOF. Otherwise, it converts (unsigned char)c as a one-byte multibyte character beginning in the initial conversion state, as if by calling mbrtowc. If the conversion succeeds, the function returns the wide-character conversion. Otherwise, it returns WEOF.


fwide

int fwide(FILE *stream, int mode);

The function determines the orientation of the stream stream. If mode is greater than zero, it first attempts to make the stream wide oriented. If mode is less than zero, it first attempts to make the stream byte oriented. In any event, the function returns:

  • A value greater than zero if the stream is left wide-oriented.
  • Zero if the stream is left unbound.
  • A value less than zero if the stream is left byte-oriented.

In no event will the function alter the orientation of a stream after it has been oriented.


mbrlen

size_t mbrlen(const char *s, size_t n, mbstate_t *ps);

The function is equivalent to the call:

mbrtowc (0, s, n, ps != 0 ? ps : &internal)

where internal is an object of type mbstate_t internal to the mbrlen function. At program startup, internal is initialized to the initial conversion state. No other library function alters the value stored in internal.

The function returns:

  • (size_t)-2 if, after converting all n characters, the resulting conversion state indicates an incomplete multibyte character.
  • (size_t)-1 if the function detects an encoding error before completing the next multibyte character, in which case the function stores the value EILSEQ in errno and leaves the resulting conversion state undefined.
  • Zero, if the next completed character is a null character, in which case the resulting conversion state is the initial conversion state.
  • x, the number of bytes needed to complete the next muitibyte character, in which case the resulting conversion state indicates that x bytes have been converted.

Thus, mbrlen effectively returns the number of bytes that would be consumed in successfully converting a multibyte character to a wide character (without storing the converted wide character), or an error code if the conversion cannot succeed.


mbrtowc

size_t mbrtowc(wchar_t *pwc, const char *s, size_t n, mbstate_t *ps);

The function determines the number of bytes in a multibyte string that completes the next multibyte character, if possible.

If ps is not a null pointer, the conversion state for the multibyte string is assumed to be *ps. Otherwise, it is assumed to be &internal, where internal is an object of type mbstate_t internal to the mbrtowc function. At program startup, internal is initialized to the initial conversion state. No other library function alters the value stored in internal.

If s is not a null pointer, the function determines x, the number of bytes in the multibyte string s that complete or contribute to the next multibyte character. (x cannot be greater than n.) Otherwise, the function effectively returns mbrtowc(0, "", 1, ps), ignoring pwc and n. (The function thus returns zero only if the conversion state indicates that no incomplete multibyte character is pending from a previous call to mbrlen, mbrtowc, or mbsrtowcs for the same string and conversion state.)

If pwc is not a null pointer, the function converts a completed multibyte character to its corresponding wide-character value and stores that value in *pwc.

The function returns:

  • (size_t)-2 if, after converting all n characters, the resulting conversion state indicates an incomplete multibyte character.
  • (size_t)-1 if the function detects an encoding error before completing the next multibyte character, in which case the function stores the value EILSEQ in errno and leaves the resulting conversion state undefined.
  • Zero, if the next completed character is a null character, in which case the resulting conversion state is the initial conversion state.
  • x, the number of bytes needed to complete the next muitibyte character, in which case the resulting conversion state indicates that x bytes have been converted.


mbsinit

int mbsinit(const mbstate_t *ps);

The function returns a nonzero value if ps is a null pointer or if *ps designates an initial conversion state. Otherwise, it returns zero.


mbsrtowcs

size_t mbsrtowcs(wchar_t *dst, const char **src, size_t len, mbstate_t *ps);

The function converts the multibyte string beginning at *src to a sequence of wide characters as if by repeated calls of the form:

x = mbrtowc(dst, *src, n, ps != 0 ? ps : &internal)

where n is some value > 0 and internal is an object of type mbstate_t internal to the mbsrtowcs function. At program startup, internal is initialized to the initial conversion state. No other library function alters the value stored in internal.

If dst is not a null pointer, the mbsrtowcs function stores len wide characters , at most, by calls to mbrtowc. The function effectively increments dst by one and *src by x after each call to mbrtowc that stores a converted wide character. After a call that returns zero, mbsrtowcs stores a null wide character at dst and stores a null pointer at *src.

If dst is a null pointer, len is effectively assigned a large value.

The function returns:

  • (size_t)-1, if a call to mbrtowc returns (size_t)-1, indicating that it has detected an encoding error before completing the next multibyte character.
  • The number of multibyte characters successfully converted, not including the terminating null character.


mbstate_t

typedef o-type mbstate_t;

The type is an object type o-type that can represent a conversion state for any of the functions mbrlen, mbrtowc, mbsrtowcs, wcrtomb, or wcsrtombs. A definition of the form:

mbstate_t mbst = {0};

ensures that mbst represents the initial conversion state. Note, however, that other values stored in an object of type mbstate_t can also represent this state. To test safely for this state, use the function mbsinit.


wcrtomb

size_t wcrtomb(char *s, wchar_t wc, mbstate_t *ps);

The function determines the number of bytes needed to represent the wide character wc as a multibyte character, if possible. (Not all values representable as type wchar_t are necessarily valid wide-character codes.)

If ps is not a null pointer, the conversion state for the multibyte string is assumed to be *ps. Otherwise, it is assumed to be &internal, where internal is an object of type mbstate_t internal to the wcrtomb function. At program startup, internal is initialized to the initial conversion state. No other library function alters the value stored in internal.

If s is not a null pointer and wc is a valid wide-character code, the function determines x, the number of bytes needed to represent wc as a multibyte character, and stores the converted bytes in the array of char beginning at s. (x cannot be greater than MB_CUR_MAX.) If wc is a null wide character, the function stores any shift sequence needed to restore the initial shift state, followed by a null byte. The resulting conversion state is the initial conversion state.

If s is a null pointer, the function effectively returns wcrtomb(buf, L'\0', ps), where buf is a buffer internal to the function. (The function thus returns the number of bytes needed to restore the initial conversion state and to terminate the multibyte string pending from a previous call to wcrtomb or wcsrtombs for the same string and conversion state.)

The function returns:

  • (size_t)-1 if wc is an invalid wide-character code, in which case the function stores the value EILSEQ in errno and leaves the resulting conversion state undefined.
  • x, the number of bytes needed to complete the next muitibyte character, in which case the resulting conversion state indicates that x bytes have been generated.


wcsrtombs

size_t wcsrtombs(char *dst, const wchar_t **src, size_t len, mbstate_t *ps);

The function converts the wide-character string beginning at *src to a sequence of multibyte characters as if by repeated calls of the form:

x = wcrtomb(dst ? dst : buf, *src, ps != 0 ? ps : &internal)

where buf is an array of type char and internal is an object of type mbstate_t, both internal to the wcsrtombs function. At program startup, internal is initialized to the initial conversion state. No other library function alters the value stored in internal.

If dst is not a null pointer, the wcsrtombs function stores len bytes, at most, by calls to wcrtomb. The function effectively increments dst by x and *src by one after each call to wcrtomb that stores a complete converted multibyte character in the remaining space available. After a call that stores a complete null multibyte character at dst (including any shift sequence needed to restore the initial shift state), the function stores a null pointer at *src.

If dst is a null pointer, len is effectively assigned a large value.

The function returns:

  • (size_t)-1, if a call to wcrtomb returns (size_t)-1, indicating that it has detected an invalid wide-character code.
  • The number of bytes successfully converted, not including the terminating null byte.


wctob

int wctob(wint_t c);

The function determines whether c can be represented as a one-byte multibyte character x, beginning in the initial shift state. (It effectively calls wcrtomb to make the conversion.) If so, the function returns x. Otherwise, it returns WEOF.


wmemchr

wchar_t *wmemchr(const wchar_t *s, wchar_t c, size_t n); [not in C++]
const wchar_t *wmemchr(const wchar_t *s, wchar_t c, size_t n); [C++ only]
wchar_t *wmemchr(wchar_t *s, wchar_t c, size_t n); [C++ only]

The function searches for the first element of an array beginning at the address s with size n, that equals c. If successful, it returns the address of the matching element; otherwise, it returns a null pointer.


wmemcmp

int wmemcmp(const wchar_t *s1, const wchar_t *s2, size_t n);

The function compares successive elements from two arrays beginning at the addresses s1 and s2 (both of size n), until it finds elements that are not equal.

  • If all elements are equal, the function returns zero.
  • If the differing element from s1 is greater than the element from s2, the function returns a positive number.
  • Otherwise, the function returns a negative number.


wmemcpy

wchar_t *wmemcpy(wchar_t *s1, const wchar_t *s2, size_t n);

The function copies the array beginning at the address s2 to the array beginning at the address s1 (both of size n). It returns s1. The elements of the arrays can be accessed and stored in any order.


wmemmove

wchar_t *wmemmove(wchar_t *s1, const wchar_t *s2, size_t n);

The function copies the array beginning at s2 to the array beginning at s1 (both of size n). It returns s1. If the arrays overlap, the function accesses each of the element values from s2 before it stores a new value in that element, so the copy is not corrupted.


wmemset

wchar_t *wmemset(wchar_t *s, wchar_t c, size_t n);

The function stores c in each of the elements of the array beginning at s, with size n. It returns s.


 STL Sample Programs

STL Sample Programs

Following is an alphabetic list of 118 STL sample programs.

  • abs
  • accumulate, copy, vector::push_back
  • adjacent_difference, vector::push_back
  • advance
  • Basic Math Functions
  • basic_string::append
  • basic_string size and resize
  • binary_function Structure
  • count
  • count_if
  • deque::assign and deque::swap
  • deque::begin and deque::end
  • deque::erase and deque::clear
  • deque::front and deque::back
  • deque::insert
  • deque::operator[] and deque::at
  • deque::push_back and deque::pop_back
  • deque::push_front, deque::pop_front
  • deque::rbegin and deque::rend
  • deque::size and deque::resize
  • distance
  • exp, log, and log10
  • find
  • find_if
  • for_each
  • generate
  • generate_n
  • heap
  • heap (predicate version)
  • includes
  • includes (predicate version)
  • inner_product
  • inplace_merge
  • inplace_merge (predicate version)
  • iter_swap
  • list::assign
  • list::back, list::front
  • deque::insert
  • list::list
  • lower_bound
  • lower_bound (predicate version)
  • make_pair
  • map::insert, map::find, and map::end
  • max_element
  • max_element (predicate version)
  • map::max_size, clear, erase, size
  • merge
  • merge (predicate version)
  • min_element
  • min_element (predicate version)
  • new operator
  • next_permutation
  • next_permutation (predicate version)
  • nth_element
  • nth_element (predicate version)
  • Members of the numeric_limits Class
  • operator == and operator < deque
  • Pair Logical Operator
  • partial_sort
  • partial_sort_copy
  • partial_sort_copy (predicate version)
  • partial_sort (predicate version)
  • partial_sum
  • partition
  • prev_permutation
  • priority_queue functions
  • queue functions
  • random_shuffle
  • random_shuffle
  • remove
  • remove_copy
  • remove_copy_if
  • remove_if
  • replace
  • replace_copy
  • replace_copy_if
  • replace_if
  • reverse
  • reverse_copy
  • rotate
  • rotate_copy
  • set::(lower_, upper_)bound, equal_range
  • set::(key_, value_)comp
  • set::count
  • set::empty and set::clear
  • set::find
  • set::max_size
  • set::rbegin and set::rend
  • set::size
  • set::swap, begin, end
  • sqrt and pow
  • stack::operator==
  • stack::operator<
  • stack::size
  • stack::top and stack::empty
  • string::getline
  • string::operator==
  • string::operator>
  • string::operator>=
  • string::operator>>
  • string::operator<
  • string::operator<=
  • string::operator<<
  • string::operator+
  • string::operator!=
  • Trigonometry Functions
  • unary_function<> Structure
  • upper_bound
  • upper_bound (predicate version)
  • Vector Class, operator==
  • vector::empty, erase, and push_back
  • vector::front and vector::back
  • Vector Class, operator<
  • vector::push_back and vector::pop_back
  • vector::size and vector::capacity


abs (STL Sample)

The sample code below illustrates how to use the abs STL function in Visual C++.

Required Header:
<valarray>

Prototype:

   template<class T>
   valarray<T> abs(const valarray<T>& x);

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
The sample declares a valarray of integers and uses the abs()STL function to get the absolute value for each array element.

Sample Code:

//////////////////////////////////////////////////////////////////////
//
// Compile options needed: None
//
// <filename> :  main.cpp
//
// Functions:
//
//    abs
//
//////////////////////////////////////////////////////////////////////

#include <iostream>                 // for i/o functions
#include <valarray>                 // for valarray

using namespace std;

#define ARRAY_SIZE  10              // array size
typedef valarray<int> INTVALARRAY;  // type for valarray of ints

void main()
{
    // Initialize val_array to 0, -1, -2, etc.
    INTVALARRAY val_array(ARRAY_SIZE);
    for (int i = 0; i < ARRAY_SIZE; i++)
        val_array[i] = -i;

    // Display the size of val_array.
    cout << "Size of val_array = " << val_array.size() << "\n\n";

    // Display the values of val_array before calling abs().
    cout << "The values of val_array before calling abs():\n";
    for (i = 0; i < ARRAY_SIZE; i++)
        cout << val_array[i] << "    ";
    cout << "\n\n";

    // Display the result of val_array after calling abs().
    INTVALARRAY abs_array = abs(val_array);
    cout << "The result of val_array after calling abs():\n";
    for (i = 0; i < ARRAY_SIZE; i++)
        cout << abs_array[i] << "     ";
    cout << "\n\n";
}

Program Output is:

Size of val_array = 10

The values of val_array before calling abs():
0    -1    -2    -3    -4    -5    -6    -7    -8    -9

The result of val_array after calling abs():
0     1     2     3     4     5     6     7     8     9


accumulate, copy, vector::push_back(STL Sample)

The sample code below illustrates how to use the accumulate, copy, and vector::push_back STL functions in Visual C++.

Required Header:
<numeric>

Prototype:

template<class InputIterator, class _TYPE> inline
      _TYPE accumulate(InputIterator first, InputIterator last, _TYPE init)

template<class InputIterator, class _TYPE, class BinaryOperator> inline
     _TYPE accumulate(InputIterator first, InputIterator last, _TYPE init, BinaryOperator binary_op)

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
The accumulate function initializes an accumulator acc with an initial value init and then modifies it with acc = acc + *i or acc = binary_op(acc,*i) for every iterator i in the range [first, last) in order. Normally, the accumulate function is used to sum the numeric elements of a vector. However, it can also be used to do other useful work such as concatenating a vector of strings.

Sample Code:

///////////////////////////////////////////////////////////////////////
//
// Compile options needed: /GX
//
// accumulate.cpp : Demonstrates the use of accumulate()
//
// Description of accumulate(first,last,init)
//                accumulate(first,last,init,binary_op):
//
//    Initializes the accumulator acc with the initial value init
//        acc = init
//    and then modifies it with
//        acc  =  acc + *i
//    or
//        acc = binary_op(acc, *i)
//    for every iterator i in the range [first, last) in order.
///////////////////////////////////////////////////////////////////////

// turn off warning about symbols too long for debugger
#pragma warning (disable : 4786)

#include <iostream>
#include <numeric>
#include <functional>
#include <vector>
#include <iterator>
#include <string>

using namespace std;

typedef vector < float > FloatArray;
typedef vector < string > StringArray;
typedef ostream_iterator <float, char, char_traits <char> > FloatOstreamIt;

void main ()
{
    // a vector of floats
    FloatArray rgFA;

    // an ostream iterator that outputs a float to cout terminated
    // by a space
    FloatOstreamIt OstreamIt(cout," ");

    // Initialize the array to 1,1/2,1/3,...
    for (int i=0; i<10; i++) rgFA.push_back(1.0f/(i+1));

    // Print the array
    copy(rgFA.begin(),rgFA.end(),OstreamIt);
    cout << endl;

    // Sum the array
    cout << "The sum of 1 + 1/2 + 1/3 + ... + 1/10 is "
         << accumulate(rgFA.begin(),rgFA.end(),0.0f)
         << endl;

    // Compute the product of the array
    cout << "The product of 1 * 1/2 * 1/3 * ... * 1/10 is "
         << accumulate(rgFA.begin(),rgFA.end(),1.0f,multiplies<float>())
         << endl;

    // Initialize array of strings
    StringArray rgs;
    rgs.push_back("This ");
    rgs.push_back("is ");
    rgs.push_back("one ");
    rgs.push_back("sentence. ");

    // Concatenate the strings in the array and print the sentence
    cout << "The concatenated vector of strings: "
         << accumulate(rgs.begin(),rgs.end(),string(""))
         << endl;
}

Program Output is:

1 0.5 0.333333 0.25 0.2 0.166667 0.142857 0.125 0.111111 0.1
The sum of 1 + 1/2 + 1/3 + ... + 1/10 is 2.92897
The product of 1 * 1/2 * 1/3 * ... * 1/10 is 2.75573e-007
The concatenated vector of strings: This is one sentence.


adjacent_difference, vector::push_back (STL Sample)

The sample code below illustrates how to use the adjacent_difference and vector::push_back STL functions in Visual C++.

Required Header:
<numeric>

Prototype:

template<class InputIterator, class OutputIterator> inline
     OutputIterator adjacent_difference(InputIterator first, InputIterator last, OutputIterator result)

template<class InputIterator, class OutputIterator, class BinaryOperator> inline
     OutputIterator adjacent_difference(InputIterator first, InputIterator last, OutputIterator result,
     BinaryOperator binary_op)

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
Assigns to every element referred to by iterator i in the range [result + 1, result + (last - first)) a value correspondingly equal to *(first + (i - result)) - *(first + (i - result) - 1) or binary_op (*(first + (i - result)), *(first + (i - result) - 1)). Result gets the value of *first.

Sample Code:

///////////////////////////////////////////////////////////////////////
//
// Compile options needed: /GX
//
// adj_diff.cpp : Demonstrates the use of adjacent_difference()
//
// Description of adjacent_difference(first,last,result)
//                adjacent_difference(first,last,result,binary_op):
//
//    Assigns to every element referred to by iterator i in the range
//    [result + 1, result + (last - first))
//    a value correspondingly equal to
//    *(first + (i - result)) - *(first + (i - result) - 1)
//    or
//    binary_op(*(first + (i - result)), *(first + (i - result) - 1)).
//    Result gets the value of *first.
///////////////////////////////////////////////////////////////////////

#include <iostream>
#include <numeric>
#include <functional>
#include <vector>
#include <iterator>

using namespace std;

typedef vector < int > IntegerArray;
typedef ostream_iterator < int, char, char_traits<char> > IntOstreamIt;

void main ()
{
    // an ostream iterator that outputs an int to cout terminated
    // by a space
    IntOstreamIt itOstream(cout," ");

    // Initialize the array
    // Suppose that you are taking a trip and can measure
    // the miles traveled from your city of origin
    // to the city you are traveling through
    IntegerArray rgIA;
    rgIA.push_back(5661); // San Francisco to Berlin
    rgIA.push_back(7456); // to Cairo
    rgIA.push_back(10995); // to Calcutta
    rgIA.push_back(17019); // to Cape Town
    rgIA.push_back(24394); // to Hong Kong
    rgIA.push_back(30376); // to London
    rgIA.push_back(35758); // to Los Angeles

    // Print the array
    copy(rgIA.begin(),rgIA.end(),itOstream);
    cout << endl;

    // Suppose that you now want the distance between each
    // of the cities that you traveled to. You can easily
    // find it with adjacent_difference()
    IntegerArray rgDifferences(7);
    IntegerArray::iterator itDifferences = rgDifferences.begin();
    adjacent_difference(rgIA.begin(),rgIA.end(),itDifferences);

    // Print the differences
    // Remember that the first item in the differences array is
    // not a difference, but is unused space
    cout << "The adjacent differences are: ";
    copy(rgDifferences.begin()+1,rgDifferences.end(),itOstream);
    cout << endl;

    // Suppose that you now want to know which adjacent differences
    // are greater. If you have [a,b,c], you would like [1,0] if a>b
    // and b<=c.
    // You are using less() rather than greater() because
    // adjacent_difference() reverses the parameters. For example,
    // if a and b are adjacent, adjacent_difference() calls
    // less(b,a). See the explanation at the top of this file
    // for a more exact description.
    IntegerArray rgGT(6);
    IntegerArray::iterator itGT = rgGT.begin();
    adjacent_difference(rgDifferences.begin()+1,
                        rgDifferences.end(),
                        itGT,
                        less<int>());

    // Print the greater thans
    // Remember that the first item in the differences array is
    // not a difference, but is unused space
    cout << "Which adjacent distances are greater:" << endl
         << "(If you have [a,b,c], then you have [1,0] if a>b and b<=c)"
         << endl;
    copy(rgGT.begin()+1,rgGT.end(),itOstream);
    cout << endl;
}

Program Output is:

5661 7456 10995 17019 24394 30376 35758
The adjacent differences are: 1795 3539 6024 7375 5982 5382
Which adjacent distances are greater:
(If you have [a,b,c], then you have [1,0] if a>b and b<=c)
0 0 0 1 1


Non-Predicate Version of adjacent_find (STL Sample)

The sample code below illustrates how to use the non-predicate version of the adjacent_find STL function in Visual C++.

Required Header:
<algorithm>

Prototype:

template<class ForwardIterator> inline
     ForwardIterator adjacent_find(ForwardIterator first, ForwardIterator last) ;

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
The adjacent_find algorithm finds consecutive pairs of matching elements in a sequence. The adjacent_find algorithm returns an iterator referencing the first consecutive matching element in the range (first, last), or last if there are no such elements. Comparison is done using operator== in this non-predicate version of the algorithm.

Sample Code:

//////////////////////////////////////////////////////////////////////
//
// Compile options needed: /GX
//
// adfind.cpp : Illustrates how to use the  non-predicate version of
//              adjacent_find function.
//
// Functions:
//
//   adjacent_find - Locate a matching consecutive sequence in a range.
//////////////////////////////////////////////////////////////////////

#include <algorithm>
#include <iostream>

using namespace std;

void main()
{
    const int ARRAY_SIZE = 8 ;
    int IntArray[ARRAY_SIZE] = { 1, 2, 3, 4, 4, 5, 6, 7 } ;

    int *location ;   // stores the position for the first pair
                      // of matching consecutive elements.

    int i ;

    // print content of IntArray
    cout << "IntArray { " ;
    for(i = 0; i < ARRAY_SIZE; i++)
        cout << IntArray[i] << ", " ;
    cout << " }" << endl ;

    // Find the first pair of matching consecutive elements
    // in the range [first, last + 1)
    // This version performs matching using operator==
    location = adjacent_find(IntArray, IntArray + ARRAY_SIZE) ;

    //print the matching consecutive elements if any were found
    if (location != IntArray + ARRAY_SIZE)  // matching consecutive
                                            // elements found
        cout << "Found adjacent pair of matching elements: ("
        << *location << ", " << *(location + 1) << "), " <<
        "at location " << location - IntArray << endl;
    else         // no matching consecutive elements were found
        cout << "No adjacent pair of matching elements were found"
        << endl ;

}

Program Output is:

IntArray { 1, 2, 3, 4, 4, 5, 6, 7,  }
Found adjacent pair of matching elements: (4, 4), at location 3


Predicate Version of adjacent_find (STL Sample)

The sample code below illustrates how to use the predicate version of the adjacent_find STL function in Visual C++.

Required Header:
<algorithm>

Prototype:

template<class ForwardIterator, class BinaryPredicate> inline
      ForwardIterator adjacent_find(ForwardIterator first, ForwardIterator last, BinaryPredicate binary_pred) ;

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
The adjacent_find algorithm finds consecutive pairs of matching elements in a sequence. adjacent_find returns an iterator referencing the first consecutive matching element in the range [first, last), or last if there are no such elements. Comparison is done using the binary_pred function in this version of the algorithm. The binary_pred function can be any user-defined function. You could also use one of the binary function objects provided by STL.

Sample Code:

//////////////////////////////////////////////////////////////////////
//
// Compile options needed: /GX
//
// adfind.cpp : Illustrates how to use the predicate version of
//              adjacent_find function.
//
// Functions:
//
//   adjacent_find  - Locate a consecutive sequence in a range.
//////////////////////////////////////////////////////////////////////

// disable warning C4786: symbol greater than 255 character,
// okay to ignore
#pragma warning(disable: 4786)

#include <iostream>
#include <algorithm>
#include <functional>
#include <string>
#include <vector>

using namespace std;

void main()
{
    const int VECTOR_SIZE = 5 ;

    // Define a template class vector of strings
    typedef vector<string > StringVector ;

    //Define an iterator for template class vector of strings
    typedef StringVector::iterator StringVectorIt ;

    StringVector NamesVect(VECTOR_SIZE) ;   //vector containing names

    StringVectorIt location ;   // stores the position for the
                                 // first pair of matching
                                 // consecutive elements.

    StringVectorIt start, end, it ;

    // Initialize vector NamesVect
    NamesVect[0] = "Aladdin" ;
    NamesVect[1] = "Jasmine" ;
    NamesVect[2] = "Mickey" ;
    NamesVect[3] = "Minnie" ;
    NamesVect[4] = "Goofy" ;

    start = NamesVect.begin() ;   // location of first
                                  // element of NamesVect

    end = NamesVect.end() ;       // one past the location
                                  // last element of NamesVect

    // print content of NamesVect
    cout << "NamesVect { " ;
    for(it = start; it != end; it++)
        cout << *it << ", " ;
    cout << " }\n" << endl ;

    // Find the first name that is lexicographically greater
    // than the following name in the range [first, last + 1).
    // This version performs matching using binary predicate
    // function greater<string>
    location = adjacent_find(start, end, greater<string>()) ;

    // print the first pair of strings such that the first name is
    // lexicographically greater than the second.
    if (location != end)
        cout << "(" << *location << ", " << *(location + 1) << ")"
        << " the first pair of strings in NamesVect such that\n"
        << "the first name is lexicographically greater than"
        << "the second\n" << endl ;
    else
        cout << "No consecutive pair of strings found such that\n"
        << "the first name is lexicographically greater than "
        << "the second\n" << endl ;

}

Program Output is:

NamesVect { Aladdin, Jasmine, Mickey, Minnie, Goofy,  }

(Minnie, Goofy) the first pair of strings in NamesVect such that
the first name is lexicographically greater than the second


advance (STL Sample)

The sample code below illustrates how to use the advance STL function in Visual C++.

Required Header:
<iterator>

Prototype:

template<class InIt, class Dist>
     void advance(InIt& it, Dist n);

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
The advance function accepts two parameters:
- InIt: The iterator to advance.
- Dist: The number of elements to increment the iterator by.
The advance function advances the iterator n times. If the iterator is a random-access iterator type, the function evaluates the expression as iterator += n. Otherwise, it performs each increment by evaluating: ++iterator. If the iterator is an input or forward iterator type, n must not be negative. NOTE: The class/parameter names in the prototype may not match the version in the header file. Some have been modified to improve readability.

Sample Code:

//////////////////////////////////////////////////////////////////////
//
// Compile options needed: /GX
//
// <filename> :  Advance.cpp
//
// Functions:
//
//    advance()
//////////////////////////////////////////////////////////////////////

/* Compile options needed: /GX
*/
#include <iostream>
#include <string>
#include <list>
#pragma warning (disable:4786)

using namespace std ;

typedef list<string> STRLIST;

void main() {
    STRLIST List;
    STRLIST::iterator iList;
    STRLIST::difference_type dTheDiff;

    List.push_back("A1");
    List.push_back("B2");
    List.push_back("C3");
    List.push_back("D4");
    List.push_back("E5");
    List.push_back("F6");
    List.push_back("G7");

    // Print out the list
    iList=List.begin();
    cout << "The list is: ";
    for (int i = 0; i < 7 ; i++, iList++)
        cout << *iList  << "  ";

    // Initialize to the first element"
    iList=List.begin();
    cout << "\n\nAdvance to the 3rd element." << endl;
    advance(iList,2);
    cout << "The element is " << *iList << endl;
    dTheDiff = distance( List.begin(), iList);
}

Program Output is:

The list is: A1  B2  C3  D4  E5  F6  G7

Advance to the 3rd element.

The element is C3


Basic Math (STL Sample)

The sample code below illustrates how to use some basic math functions in Visual C++.

Required Header:
< functional >

Prototype:

template<class _TYPE>
     struct plus : binary_function<_TYPE, _TYPE, _TYPE>
     {
        _TYPE operator()(const _TYPE& _X, const _TYPE& _Y) const
                                         {return (_X + _Y); }
     };
template<class _TYPE>
     struct minus : binary_function<_TYPE, _TYPE, _TYPE>
     {
        _TYPE operator()(const _TYPE& _X, const _TYPE& _Y) const
                                         {return (_X - _Y); }
     };
template<class _TYPE>
     struct times : binary_function<_TYPE, _TYPE, _TYPE>
     {
       _TYPE operator()(const _TYPE& _X, const _TYPE& _Y) const
                                         {return (_X * _Y); }
     };
template<class _TYPE>
     struct divides : binary_function<_TYPE, _TYPE, _TYPE>
     {
       _TYPE operator()(const _TYPE& _X, const _TYPE& _Y) const
                                         {return (_X / _Y); }
     };
template<class _TYPE>
     struct modulus : binary_function<_TYPE, _TYPE, _TYPE>
     {
       _TYPE operator()(const _TYPE& _X, const _TYPE& _Y) const
                                         {return (_X % _Y); }
     };

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
This sample uses a class derived from all five basic math structures: plus, minus, times, divides, and modulus, using an integer as the templated operand.

Sample Code:

////////////////////////////////////////////////////////////////
//
// Compile options needed: none
//
// mathfunc.cpp - Illustrating the basic STL math
//                functions.
//
// Structures: plus<A>    - Adds data type A object to
//                          a class object derived from plus.
//             minus<A>   - Subtracts data type A.
//             multiplies<A>   - Multiplies object by data type A.
//             divides<A> - Divides object by data type A.
//             modulus<A> - Returns object modulo A.
/////////////////////////////////////////////////////////////////

#include <functional>
#include <iostream>

using namespace std ;

class MathOps : public plus<int>, public minus<int>,
                 public multiplies<int>, public divides<int>,
                 public modulus<int>
{
public:
  int value;
  MathOps(){value=0;}
  MathOps(int x){value=x;}
  result_type operator+(second_argument_type add2)
                            {return value + add2;}
  result_type operator-(second_argument_type sub2)
                            {return value - sub2;}
  result_type operator*(second_argument_type mult2)
                            {return value * mult2;}
  result_type operator/(second_argument_type div2)
                            {return value / div2;}
  result_type operator%(second_argument_type mod2)
                            {return value % mod2;}
  friend ostream& operator<<(ostream& os, const MathOps& obj ) ;
};

ostream& operator<<(ostream& os, const MathOps& obj )
{
       os << obj.value ;
       return os ;
}

void main(void)
{
  MathOps one,two,three,four,five,six;

  cout << "Using MathOps class..." << endl ;

  one = 18;
  cout << "one = " << one << endl ;

  two = one + 1;
  cout << "two = one + 1 = " << two << endl ;

  three = two - 2;
  cout << "three = two - 2 = " << three << endl ;

  four = three * 3;
  cout << "four = three * 3 = " << four << endl ;

  five = four / 4;
  cout << "five = four / 4 = " << five << endl ;

  six = five % 5;
  cout << "six = five % 5 = " << six << endl ;
}

Program Output is:

Using MathOps class...
one = 18
two = one + 1 = 19
three = two - 2 = 17
four = three * 3 = 51
five = four / 4 = 12
six = five % 5 = 2


basic_string::append (STL Sample)

The sample code below illustrates how to use the basic_string::append STL function in Visual C++.

Required Header:
<string>

Prototype:

     string& append(const basic_string& _X);

     string& append(const basic_string& _X, size_type pos, size_type count);

     string& append(const element_type *_S, size_type count);

     string& append(const element_type *_S);

     string& append(size_type count, element_type _C);

     string& append(Iterator first, Iterator last);

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
The append member functions of the basic_string append elements to the end of the string. The different forms of the function provide alternate ways to specify the source of the elements that will be appended. The append functions return a reference to the string to which the elements were appended.

Sample Code:

//////////////////////////////////////////////////////////////////////
//
// Compile options needed: /GX
//
// bsappend.cpp : Illustrates how to use the string append member
//                            function.
//
// Functions:
//
//    string::append - appends a sequence of elements to the
//                           current string.
//////////////////////////////////////////////////////////////////////

#include <string>
#include <iostream>

using namespace std ;

void main()
{
    string str1("012");
    string str2("345");

    cout << "str1 = " << str1.c_str() << endl;

    // append str2 to str1
    str1.append(str2);

    cout << "str1 = " << str1.c_str() << endl;

    // append the last 2 items in str2 to str1
    str2 = "567";
    str1.append(str2, 1, 2);    // begin at pos 1, append 2 elements

    cout << "str1 = " << str1.c_str() << endl;

    // append the first 2 items from an array of the element type
    char achTest[] = {'8', '9', 'A'};
    str1.append(achTest, 2);

    cout << "str1 = " << str1.c_str() << endl;

    // append all of a string literal to str1
    char szTest[] = "ABC";
    str1.append(szTest);

    cout << "str1 = " << str1.c_str() << endl;

    // append one item of the element type
    str1.append(1, 'D');

    cout << "str1 = " << str1.c_str() << endl;

    // append str2 to str1 using iterators
    str2 = "EF";
    str1.append (str2.begin(), str2.end());

    cout << "str1 = " << str1.c_str() << endl;
}

Program Output is:

str1 = 012
str1 = 012345
str1 = 01234567
str1 = 0123456789
str1 = 0123456789ABC
str1 = 0123456789ABCD
str1 = 0123456789ABCDEF


basic_string::find_first_of (STL Sample)

The sample code below illustrates how to use the basic_string::find_first_of STL function in Visual C++.

Required Header:
<string>

Prototype:

     size_type find_first_of(const basic_string& _X, size_type iPos = 0);
     size_type find_first_of(const element_type *_S, size_type iPos, size_type cElementsIn_S);
     size_type find_first_of(const element_type *_S, size_type iPos = 0);
     size_type find_first_of(element_type _C, size_type iPos = 0);

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
The member functions each find the first (lowest position) element of the controlled sequence at or after position iPos that matches any of the elements in the operand sequence specified by the remaining operands. If it succeeds, it returns the position. Otherwise, the function returns npos. The position returned is 0 (zero) based. The npos return value is a special value indicating that none of the elements were found.

Sample Code:

//////////////////////////////////////////////////////////////////////
//
// Compile options needed: /GX
//
// main.cpp : Demonstrates the use of the string::find_first_of().
//
// Functions:
//
//    string::find_first_of() - find the first instance in the
//         controlled string of any of the elements specified by the
//         parameters. The search begins at an optionally-supplied
//         position in the controlled string.
//////////////////////////////////////////////////////////////////////

#include <string>
#include <iostream>

using namespace std ;

void main()
{
    string str1("Heartbeat");
    string str2("abcde");
    int iPos = 0;

    cout << "The string to search is '" << str1.c_str() << "'"
         << endl;

    // find the first instance in str1 of any characters in str2
    iPos = str1.find_first_of (str2, 0);  // 0 is default position

    cout << "Element in '" << str2.c_str() << "' found at position "
         << iPos << endl;

    // start looking in the third position...
    iPos = str1.find_first_of (str2, 2);

    cout << "Element in '" << str2.c_str() << "' found at position "
         << iPos << endl;

    // use an array of the element type as the set of elements to
    // search for; look for anything after the fourth position
    char achVowels[] = {'a', 'e', 'i', 'o', 'u'};
    iPos = str1.find_first_of (achVowels, 4, sizeof(achVowels));

    cout << "Element in '";
    for (int i = 0; i < sizeof (achVowels); i++)
        cout << achVowels[i];
    cout << "' found at position " << iPos << endl;

    // use a string literal to specify the set of elements
    char szVowels[] = "aeiou";
    iPos = str1.find_first_of (szVowels, 0);  // 0 is default position

    cout << "Element in '" << szVowels << "' found at position "
         << iPos << endl;

    // look for a specific character beginning in the third position
    iPos = str1.find_first_of ('e', 2);

    cout << "'e' found at position " << iPos << endl;
}

Program Output is:

The string to search is 'Heartbeat'
Element in 'abcde' found at position 1
Element in 'abcde' found at position 2
Element in 'aeiou' found at position 6
Element in 'aeiou' found at position 1
'e' found at position 6


basic_string size and resize (STL Sample)

The sample code below illustrates how to use the basic_string size and resize STL functions in Visual C++.

Required Header:
<string>

Prototype:

   size_type size() const;

   void resize(size_type n, E c = E());

   resize is defined in header xstring which is included indirectly.

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
The size function returns the length of the sequence. The resize function changes the size to the length specified by the first parameter. If the sequence is made longer, the function appends elements with the value of the second parameter. This value defaults to a null. The output of the sample code shows spaces for the null characters. operator<< reads the size of string and outputs each character in the string one at a time.

Sample Code:

//////////////////////////////////////////////////////////////////////
//
// Compile options needed: /GX
//
// <filename> :  size.cpp
//
// Functions:
//
//    size()
//    resize() ; Defined in header xstring which is included indirectly.
//////////////////////////////////////////////////////////////////////

/* Compile options needed: /GX
*/
#include <iostream>
#include <string>

using namespace std;

void main()
{
    string TestString = "1111122222333334444455555";
    cout << TestString << "\n  size: " << TestString.size() << endl;
    TestString.resize(5);
    cout << TestString << "\n  size: " << TestString.size() << endl;
    TestString.resize(10);
    cout << TestString << "\n  size: " << TestString.size() << endl;
    TestString.resize(15,'6');
    cout << TestString << "\n  size: " << TestString.size() << endl;
}

Program Output is:

1111122222333334444455555
  size: 25
11111
  size: 5
11111
  size: 10
11111     66666
  size: 15


binary_function Structure (STL Sample)

The sample code below illustrates how to use the binary_function structure in Visual C++.

Required Header:
< functional >

Prototype:

template<class _A1, class _A2, class _R>
     struct binary_function
     {
         typedef _A1 first_argument_type;
         typedef _A2 second_argument_type;
         typedef _R result_type;
     };

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
The binary_function<A,B,C> class is used as a base class to allow the user to easily define binary operator functions that take data types A and B as arguments and return data type C objects.

Sample Code:

////////////////////////////////////////////
//
// Compile options needed: /GX
//
// binfunc.cpp : Illustrating the binary_function
//               structure.
//
// Structure used: binary_function<A,B,C> - base
//                 class used to create operator
//                 functions taking data types A
//                 and B and returning data type C.
////////////////////////////////////////////

#include <functional>
#include <iostream>

using namespace std ;

class binary_test : public binary_function<binary_test &,int,float>
{
public:
  float value;
  binary_test(){value=10.0;}
  binary_test(float x){value=x;}
  result_type operator<<(second_argument_type arg2);
};

binary_test::result_type
binary_test::operator<<(binary_test::second_argument_type arg2)
{
  value = ((int)value) << arg2;
  cout << "New value after shift is" << value << endl;
  return value;
}

void main(void)
{
  binary_test item;

  cout << "Begin" << endl;
  item = item << 2;
}

Program Output is:

Begin
New value after shift is 40.0


count (STL Sample)

The sample code below illustrates how to use the count STL function in Visual C++.

Required Header:
<algorithm>

Prototype:

template<class InputIterator, class T> inline
     size_t count(InputIterator first, InputIterator last, const T& value)

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
The count algorithm counts the number of elements in the range [first, last +1) that match value and returns the number of matching elements.

Sample Code:

//////////////////////////////////////////////////////////////////////
//
// Compile options needed: /GX
//
// count.cpp : Illustrates how to use the count function.
//
// Functions:
//
//    count  - Count items in a range that match a value.
//////////////////////////////////////////////////////////////////////

// disable warning C4786: symbol greater than 255 character,
// okay to ignore
#pragma warning(disable: 4786)

#include <iostream>
#include <algorithm>
#include <functional>
#include <string>
#include <vector>

using namespace std;

void main()
{
    const int VECTOR_SIZE = 8 ;

    // Define a template class vector of strings
    typedef vector<string > StringVector ;

    //Define an iterator for template class vector of strings
    typedef StringVector::iterator StringVectorIt ;

    StringVector NamesVect(VECTOR_SIZE) ;   //vector containing names

    string value("Sea") ;  // stores the value used
                           // to count matching elements

    StringVectorIt start, end, it ;

    int result = 0 ;   // stores count of elements
                       // that match value.

    // Initialize vector NamesVect
    NamesVect[0] = "She" ;
    NamesVect[1] = "Sells" ;
    NamesVect[2] = "Sea" ;
    NamesVect[3] = "Shells" ;
    NamesVect[4] = "by" ;
    NamesVect[5] = "the" ;
    NamesVect[6] = "Sea" ;
    NamesVect[7] = "Shore" ;

    start = NamesVect.begin() ;   // location of first
                                  // element of NamesVect

    end = NamesVect.end() ;       // one past the location
                                  // last element of NamesVect

    // print content of NamesVect
    cout << "NamesVect { " ;
    for(it = start; it != end; it++)
        cout << *it << " " ;
    cout << " }\n" << endl ;

    // Count the number of elements in the range [first, last +1)
    // that match value.
    result = count(start, end, value) ;

    // print the count of elements that match value
    cout << "Number of elements that match \"Sea\" = "
        << result << endl  ;
}

Program Output is:

NamesVect { She Sells Sea Shells by the Sea Shore  }

Number of elements that match "Sea" = 2


count_if (STL Sample)

The sample code below illustrates how to use the count_if STL function in Visual C++.

Required Header:
<algorithm>

Prototype:

template<class InputIterator, class Predicate>  inline
     size_t count_if(InputIterator first, InputIterator last, Predicate P)

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
The count_if algorithm counts the number of elements in the range [first, last) that cause the predicate to return true, and returns the number of elements for which the predicate was true.

Sample Code:

//////////////////////////////////////////////////////////////////////
//
// Compile options needed: /GX
//
// count.cpp : Illustrates how to use the count_if function.
//
// Functions:
//
//   count_if  - Count items in a range that satisfy a predicate.
//
//   begin     - Returns an iterator that points to the first element in
//               a sequence.
//
//   end       - Returns an iterator that points one past the end of a
//               sequence.
//////////////////////////////////////////////////////////////////////

// disable warning C4786: symbol greater than 255 character,
// okay to ignore
#pragma warning(disable: 4786)

#include <iostream>
#include <algorithm>
#include <functional>
#include <string>
#include <vector>

using namespace std;

// Return true if string str starts with letter 'S'
int MatchFirstChar( const string& str)
{
    string s("S") ;
    return s == str.substr(0,1) ;
}

void main()
{
    const int VECTOR_SIZE = 8 ;

    // Define a template class vector of strings
    typedef vector<string > StringVector ;

    //Define an iterator for template class vector of strings
    typedef StringVector::iterator StringVectorIt ;

    StringVector NamesVect(VECTOR_SIZE) ;   //vector containing names

    StringVectorIt start, end, it ;

    int result = 0 ;   // stores count of elements
                       // that match value.

    // Initialize vector NamesVect
    NamesVect[0] = "She" ;
    NamesVect[1] = "Sells" ;
    NamesVect[2] = "Sea" ;
    NamesVect[3] = "Shells" ;
    NamesVect[4] = "by" ;
    NamesVect[5] = "the" ;
    NamesVect[6] = "Sea" ;
    NamesVect[7] = "Shore" ;

    start = NamesVect.begin() ;   // location of first
                                  // element of NamesVect

    end = NamesVect.end() ;       // one past the location
                                  // last element of NamesVect

    // print content of NamesVect
    cout << "NamesVect { " ;
    for(it = start; it != end; it++)
        cout << *it << " " ;
    cout << " }\n" << endl ;

    // Count the number of elements in the range [first, last +1)
    // that start with letter 'S'
    result = count_if(start, end, MatchFirstChar) ;

    // print the count of elements that start with letter 'S'
    cout << "Number of elements that start with letter \"S\" = "
        << result << endl  ;
}

Program Output is:

NamesVect { She Sells Sea Shells by the Sea Shore  }

Number of elements that start with letter "S" = 6


deque::assign and deque::swap (STL Sample)

The sample code below illustrates how to use the deque::assign and deque::swap STL functions in Visual C++.

Required Header:
< deque>

Prototype:

   void assign(const_iterator first, const_iterator last);
   void assign(size_type n, const T& x = T());
   void swap(deque& dq);

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
The first assign member function replaces the sequence controlled by *this with the sequence [first, last). The second assign member function replaces the sequence controlled by *this with a repetition of n elements of value x. The swap member function swaps the contents between *this and dq.

Sample Code:

//////////////////////////////////////////////////////////////////////
//
// Compile options needed: -GX
//
// deque.cpp :
//
// Functions:
//
//    assign
//    swap
//    begin
//    end
//////////////////////////////////////////////////////////////////////

/* Compile options needed:-GX
*/
#include <iostream>
#include <deque>

using namespace std;

typedef deque<char >  CHARDEQUE;
void print_contents (CHARDEQUE  deque, char*);

void main()
{
    //create a  with  3 A's
    CHARDEQUE  a(3,'A');

    //create b with 4 B's.
    CHARDEQUE  b(4,'B');

    //print out the contents
    print_contents (a,"a");
    print_contents (b,"b");

    //swap a and b
    a.swap(b);
    print_contents (a,"a");
    print_contents (b,"b");

    // let us swap it back
        a.swap(b);
    print_contents (a,"a");
    print_contents (b,"b");

    //assign the contents of b to a
    a.assign(b.begin(),b.end());
    print_contents (a,"a");

    //assign the first two items of b to a
    a.assign(b.begin(),b.begin()+2);
    print_contents (a,"a");

    //assign 3 'Z's to a
    a.assign(3,'Z');
    print_contents (a,"a");

    }

//function to print the contents of deque
void print_contents (CHARDEQUE  deque, char *name)
{
    CHARDEQUE::iterator pdeque;

    cout <<"The contents of "<< name <<" : ";

        for(pdeque = deque.begin();
        pdeque != deque.end();
        pdeque++)
    {
        cout << *pdeque <<" " ;
    }
        cout<<endl;
}

Program Output is:

The contents of a : A A A
The contents of b : B B B B
The contents of a : B B B B
The contents of b : A A A
The contents of a : A A A
The contents of b : B B B B
The contents of a : B B B B
The contents of a : B B
The contents of a : Z Z Z


deque::begin and deque::end (STL Sample)

The sample code below illustrates how to use the deque::begin and deque::end STL functions in Visual C++.

Required Header:
< deque>

Prototype:

const_iterator begin() const;
iterator begin();

const_iterator end() const;
iterator end();

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
The begin member function returns a random-access iterator that points at the first element of the sequence, or just beyond the end of an empty sequence. The end member function returns a random-access iterator that points just beyond the end of the sequence.

Sample Code:

//////////////////////////////////////////////////////////////////////
//
// Compile options needed: -GX
//
// deque.cpp :
//
// Functions:
//
//    begin()
//    end()
//////////////////////////////////////////////////////////////////////

/* Compile options needed:-GX
*/
#include <iostream>
#include <deque>

using namespace std;

typedef deque<int >  INTDEQUE;

void main()
{

    // Create A and fill it with elements 1,2,3,4 and 5
    // using push_back function

    INTDEQUE  A;
    A.push_back(1);
    A.push_back(2);
    A.push_back(3);
    A.push_back(4);
    A.push_back(5);

    // Print the contents of A using iterator
    // and functions begin() and end()

     INTDEQUE::iterator pi;

    for(pi= A.begin();  pi !=A.end(); pi++)
    {
        cout << *pi <<" " ;
    }
        cout<<endl;
}

Program Output is:

1 2 3 4 5


deque::erase and deque::clear (STL sample)

The sample code below illustrates how to use the deque::erase and deque::clear STL functions in Visual C++.

Required Header:
< deque>

Prototype:

iterator erase(iterator iter);
iterator erase(iterator first, iterator last);
void clear() const;

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
The first erase member function removes the element of the container pointed to by iter. The second erase member function removes the elements of the container in the range [first, last). Both return an iterator that designates the first element remaining beyond any elements removed, or end() if no such element exists. Removing N elements causes N destructor calls and an assignment for each of the elements between the insertion point and the nearer end of the sequence. Removing an element at either end invalidates only iterators and references that designate the erased elements. Otherwise, erasing an element invalidates all iterators and references. The clear member function calls erase( begin(), end()).

Sample Code:

//////////////////////////////////////////////////////////////////////
//
// Compile options needed: -GX
//
// deque.cpp :
//
// Functions:
//
//    erase
//    clear
//    begin
//    end
//////////////////////////////////////////////////////////////////////

/* Compile options needed:-GX
*/
#include <iostream>
#include <deque>

using namespace std;

typedef deque<int >  INTDEQUE;
void print_contents (INTDEQUE  deque);

void main()
{
    // create a and with elements 1,2,3,4 and 5
    INTDEQUE  a;
    a.push_back(1);
    a.push_back(2);
    a.push_back(3);
    a.push_back(4);
    a.push_back(5);

    //print the contents
    print_contents (a);

    //  erase the second element
    a.erase(a.begin()+1);
    print_contents (a);

    //erase the last two elements
    a.erase(a.end()-2,a.end());
    print_contents (a);

    //clear a
    a.clear();
    print_contents (a);
}

void print_contents (INTDEQUE  deque) {
    INTDEQUE::iterator pdeque;

    cout <<"The output is: ";

        for(pdeque = deque.begin();
        pdeque != deque.end();
        pdeque++)
    {
        cout << *pdeque <<" " ;
    }
        cout<<endl;
}

Program Output is:

The output is: 1 2 3 4 5
The output is: 1 3 4 5
The output is: 1 3
The output is:


deque::front and deque::back (STL Sample)

The sample code below illustrates how to use the deque::front and deque::back STL functions in Visual C++.

Required Header:
< deque>

Prototype:

   reference front();
   const_reference front() const;

   reference back();
   const_reference back() const;

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
The member function front returns a reference to the first element of the controlled sequence, which must be non-empty. The member function back returns a reference to the last element of the controlled sequence, which must be non-empty.

Sample Code:

//////////////////////////////////////////////////////////////////////
//
// Compile options needed: -GX
//
// deque.cpp :
//
// Functions:
//
//    front()
//
//    back()
//////////////////////////////////////////////////////////////////////

/* Compile options needed:-GX
*/
#include <iostream>
#include <deque>

using namespace std;

typedef deque<char >  CHARDEQUE;
void print_contents (CHARDEQUE  deque, char*);

void main()
{
    //create a  with  A, B, C and D
    CHARDEQUE  a;
    a.push_back('A');
    a.push_back('B');
    a.push_back('C');
    a.push_back('D');

    //print out the contents
    print_contents (a,"a");

    cout <<"The first element of a is " <<a.front() <<endl;

    cout <<"The last element of a is " <<a.back() <<endl;

    //now let us modify the first and last elements
    //using reference ,front() and back()

    CHARDEQUE::reference reffront=a.front();
    CHARDEQUE::reference refback=a.back();

    reffront='X';
    refback='Y';

     //print out the contents
     print_contents (a,"a");

    }

//function to print the contents of deque
void print_contents (CHARDEQUE  deque, char *name)
{
    CHARDEQUE::iterator pdeque;

    cout <<"The contents of "<< name <<" : ";

        for(pdeque = deque.begin();
        pdeque != deque.end();
        pdeque++)
    {
        cout << *pdeque <<" " ;
    }
        cout<<endl;
}

Program Output is:

The contents of a : A B C D

The first element of a is A

The last element of a is D

The contents of a : X B C Y


deque::insert (STL Sample)

The sample code below illustrates how to use the deque::insert STL function in Visual C++.

Required Header:
<deque>

Prototype:

iterator insert(iterator iter, const T& x = T());
void insert(iterator iter, size_type n, const T& x);
void insert(iterator iter, const_iterator first,const_iterator last);

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
Each of these functions inserts a sequence specified by the remaining operands after the element pointed to by iter in the container. The first member function inserts a single element with value x and returns an iterator that points to the newly inserted element. The second member function inserts a repetition of n elements of value x. The third member function inserts the sequence [first, last).

Sample Code:

//////////////////////////////////////////////////////////////////////
//
// Compile options needed: -GX
//
// deque.cpp :
//
// Functions:
//
//    insert
//    begin
//    end
//////////////////////////////////////////////////////////////////////

/* Compile options needed:-GX
*/
#include <iostream>
#include <deque>

using namespace std;

typedef deque<char >  CHARDEQUE;
void print_contents (CHARDEQUE  deque);

void main()
{
    //create a with 3 A's
    CHARDEQUE  a(3,'A');

    //create b with 2 B's.
    CHARDEQUE  b(2,'B');

    //print out the contents
    print_contents (a);
    print_contents (b);

    //insert 'X' to the beginning of a
    a.insert(a.begin(),'X');
    print_contents (a);

    //insert 'Y' to the end of a
    a.insert(a.end(),'Y');
    print_contents (a);

    //inset 3 'Z's to one item before the end of a
    a.insert(a.end()-1,3,'Z');
    print_contents (a);

    //insert to the end of a from b
    a.insert(a.end(),b.begin(),b.end());
    print_contents (a);

}

//function to print the contents of deque
void print_contents (CHARDEQUE  deque)
{
    CHARDEQUE::iterator pdeque;

    cout <<"The output is: ";

    for(pdeque = deque.begin();
        pdeque != deque.end();
        pdeque++)
    {
        cout << *pdeque <<" " ;
    }
        cout<<endl;
}

Program Output is:

The output is: A A A
The output is: B B
The output is: X A A A
The output is: X A A A Y
The output is: X A A A Z Z Z Y
The output is: X A A A Z Z Z Y B B


deque::operator[] and deque::at (STL Sample)

The sample code below illustrates how to use the deque::operator[] and deque::at STL function in Visual C++.

Required Header:
< deque>

Prototype:

   const_reference operator[](size_type pos) const;
   reference operator[](size_type pos);
   const_reference operator[](difference_type _N) const;
   reference operator[](difference_type _N) const;

   const_reference at(size_type pos) const;
   reference at(size_type pos);

   bool empty() const;

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
The member function operator[] returns a reference to the element of the controlled sequence at position pos. If that position is invalid, the behavior is undefined. The member function at returns a reference to the element of the controlled sequence at position pos. If that position is invalid, the function throws an object of class out_of_range. The member function empty returns true for an empty controlled sequence.

Sample Code:

//////////////////////////////////////////////////////////////////////
//
// Compile options needed: -GX
//
// deque.cpp :
//
// Functions:
//
//    operator[]
//    at
//    empty
//    push_back
//    begin
//    end
//////////////////////////////////////////////////////////////////////

/* Compile options needed:-GX
*/
#include <iostream>
#include <deque>

using namespace std;

typedef deque<char >  CHARDEQUE;
void print_contents (CHARDEQUE  deque, char*);

void main()
{
    //create an empty deque a
    CHARDEQUE  a;

    //check whether it is empty
    if(a.empty())
        cout<<"a is empty"<<endl;
    else
        cout<<"a is not empty"<<endl;

    //inset A, B, C and D  to a
    a.push_back('A');
    a.push_back('B');
    a.push_back('C');
    a.push_back('D');

    //check again whether a is empty
    if(a.empty())
        cout<<"a is empty"<<endl;
    else
        cout<<"a is not empty"<<endl;

    //print out the contents

    print_contents (a,"a");

    cout <<"The first element of a is  " <<a[0] <<endl;
    cout <<"The first element of a is  " <<a.at(0) <<endl;

    cout <<"The last element of a is  " <<a[a.size()-1] <<endl;
    cout <<"The last element of a is  " <<a.at(a.size()-1) <<endl;
}

//function to print the contents of deque
void print_contents (CHARDEQUE  deque, char *name)
{
    CHARDEQUE::iterator pdeque;

    cout <<"The contents of "<< name <<" : ";

    for(pdeque = deque.begin();
        pdeque != deque.end();
        pdeque++)
        {
            cout << *pdeque <<" " ;
        }
    cout<<endl;
}

Program Output is:

a is empty
a is not empty
The contents of a : A B C D
The first element of a is  A
The first element of a is  A
The last element of a is  D
The last element of a is  D


deque::push_back and deque::pop_back (STL Sample)

The sample code below illustrates how to use the deque::push_back and deque::pop_back STL functions in Visual C++.

Required Header:
<deque>

Prototype:

   void push_back(const T& x);
   void pop_back();

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
The push_back function inserts an element with value x at the end of the container deque. The pop_back function removes the last element of the container deque, which must be non-empty.

Sample Code:

//////////////////////////////////////////////////////////////////////
//
// Compile options needed: -GX
//
// deque.cpp :
//
// Functions:
//
//    deque::push_back
//
//    deque::pop_back
//////////////////////////////////////////////////////////////////////

/* Compile options needed:-GX
*/

#include <iostream>
#include <deque>

using namespace std;

typedef deque<int >  INTDEQUE;
void printcontents (INTDEQUE  deque);

void main()
{

    INTDEQUE  dequetest;

    dequetest.push_back(1);
    dequetest.push_back(2);
    dequetest.push_back(3);
    printcontents (dequetest);
    dequetest.pop_back();
    printcontents (dequetest);
    dequetest.pop_back();
    printcontents (dequetest);
   }

   //function to print the contents of deque
   void printcontents (INTDEQUE  deque)
   {
       INTDEQUE::iterator pdeque;

       cout <<"The output is:"<<endl;

           for(pdeque = deque.begin();
           pdeque != deque.end();
           pdeque++)
       {
           cout << *pdeque <<endl ;
       }
   }

Program Output is:

The output is:
1
2
3
The output is:
1
2
The output is:
1


deque::push_front, deque::pop_front (STL Sample)

The sample code below illustrates how to use the deque::push_front and deque::pop_front STL functions in Visual C++.

Required Header:
<deque>

Prototype:

   void push_front(const T& x);
   void pop_front();

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
The push_front function inserts an element with value x at the beginning of the deque container. The pop_front function removes the first element of the deque container, which must be non-empty.

Sample Code:

//////////////////////////////////////////////////////////////////////
//
// Compile options needed: -GX
//
// deque.cpp :
//
// Functions:
//
//    deque::push_front
//    deque::pop_front
//////////////////////////////////////////////////////////////////////

/* Compile options needed:-GX
*/

#include <iostream>
#include <deque>

using namespace std;

typedef deque<int >  INTDEQUE;
void printcontents (INTDEQUE  deque);

void main()
{

    INTDEQUE  dequetest;

    dequetest.push_front(1);
    dequetest.push_front(2);
    dequetest.push_front(3);
    printcontents (dequetest);
    dequetest.pop_front();
    printcontents (dequetest);
    dequetest.pop_front();
    printcontents (dequetest);
}

//function to print the contents of deque
void printcontents (INTDEQUE  deque)
{
    INTDEQUE::iterator pdeque;

    cout <<"The output is:"<<endl;

        for(pdeque = deque.begin();
        pdeque != deque.end();
        pdeque++)
    {
        cout << *pdeque <<endl ;
    }
}

Program Output is:

The output is:
3
2
1
The output is:
2
1
The output is:
1


deque::rbegin and deque::rend (STL Sample)

The sample code below illustrates how to use the deque::rbegin and deque::rend STL functions in Visual C++.

Required Header:
< deque>

Prototype:

   const_reverse_iterator rbegin() const;
   reverse_iterator rbegin();

   const_reverse_iterator rend() const;
   reverse_iterator rend();

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
The rbegin member function returns a reverse iterator that points just beyond the end of the controlled sequence. Therefore, it designates the beginning of the reverse sequence. The rend member function returns a reverse iterator that points at the first element of the sequence, or just beyond the end of an empty sequence. Therefore, it designates the end of the reverse sequence.

Sample Code:

//////////////////////////////////////////////////////////////////////
//
// Compile options needed: -GX
//
// deque.cpp :
//
// Functions:
//
//    rbegin
//    rend
//    push_back
//////////////////////////////////////////////////////////////////////

/* Compile options needed:-GX
*/
#include <iostream>
#include <deque>

using namespace std;

typedef deque<int >  INTDEQUE;

void main()
{

    // Create A and fill it with elements 1,2,3,4 and 5
    // using push_back function

    INTDEQUE  A;
    A.push_back(1);
    A.push_back(2);
    A.push_back(3);
    A.push_back(4);
    A.push_back(5);

    // Now print the contents in reverse order using reverse_iterator
    // and functions rbegin() and rend()

    INTDEQUE::reverse_iterator rpi;

    for(rpi= A.rbegin();  rpi !=A.rend(); rpi++)
    {
        cout << *rpi <<" " ;
    }
        cout<<endl;
}

Program Output is:

5 4 3 2 1


deque::size and deque::resize (STL Sample)

The sample code below illustrates how to use the deque::size and deque::resize STL functions in Visual C++.

Required Header:
<deque>

Prototype:

   size_type size() const;
   void resize(size_type n, T x = T());
   size_type max_size() const;

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
The member function size returns the length of the controlled sequence. The member function resize ensures that size() henceforth returns n. If it must make the controlled sequence longer, it appends elements with value x. If no value is supplied, the default value depends upon the type. For example, if it is a deque of chars, the default is a blank. If it is a deque of ints, the default is zero. The member function max_size returns the length of the longest sequence that the object can control.

Sample Code:

//////////////////////////////////////////////////////////////////////
//
// Compile options needed: -GX
//
// deque.cpp :
//
// Functions:
//
//    size
//    resize
//    max_size
//    begin
//    end
//////////////////////////////////////////////////////////////////////

/* Compile options needed:-GX
*/
#include <iostream>
#include <deque>

using namespace std;

typedef deque<char >  CHARDEQUE;
void print_contents (CHARDEQUE  deque, char*);

void main()
{
    //create a  with  A, B, C and D
    CHARDEQUE  a;
    a.push_back('A');
    a.push_back('B');
    a.push_back('C');
    a.push_back('D');

    //print out the contents

    print_contents (a,"a");
    cout <<"max_size of a is " <<a.max_size() <<endl;
    cout <<"size of a is " <<a.size() <<endl;

    //let us increase the size to 10
    // and set the new elements to be 'X'
    a.resize(10,'X');
    print_contents (a,"a");
    cout <<"size of a is " <<a.size() <<endl;

    //let us resize it to 5
    a.resize(5);
    print_contents (a,"a");
    cout <<"size of a is " <<a.size() <<endl;
    cout <<"max_size of a is still " <<a.max_size() <<endl;

    }

//function to print the contents of deque
void print_contents (CHARDEQUE  deque, char *name)
{
    CHARDEQUE::iterator pdeque;

    cout <<"The contents of "<< name <<" : ";

        for(pdeque = deque.begin();
        pdeque != deque.end();
        pdeque++)
    {
        cout << *pdeque <<" " ;
    }
        cout<<endl;
}

Program Output is:

The contents of a : A B C D
max_size of a is 4294967295
size of a is 4
The contents of a : A B C D X X X X X X
size of a is 10
The contents of a : A B C D X
size of a is 5
max_size of a is still 4294967295


distance (STL Sample)

The sample code below illustrates how to use the distance STL function in Visual C++.

Required Header:
<iterator>

Prototype:

template<class Init, class Dist>
     Dist distance(InIt first, InIt last, Dist& n);

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
This function returns the distance between two iterators by determining how many times the first iterator would need to be incremented until it was equal to the last iterator.

Sample Code:

//////////////////////////////////////////////////////////////////////
//
// Compile options needed: /GX
//
// <filename> :  distance.cpp
//
// Functions:
//
//    distance()
//////////////////////////////////////////////////////////////////////

#include <iostream>
#include <vector>
#include <iterator>
#include <string>

using namespace std;

#pragma warning (disable:4786)
typedef vector<string > VTRLIST;

void main() {
    VTRLIST Vector;
    VTRLIST::iterator iVector;
    VTRLIST::difference_type dTheDiff;

    Vector.push_back("A1");
    Vector.push_back("B2");
    Vector.push_back("C3");
    Vector.push_back("D4");
    Vector.push_back("E5");
    Vector.push_back("F6");
    Vector.push_back("G7");

    // Print out the list
    iVector=Vector.begin();
    cout << "The list is: ";
    for (int i = 0; i < 7 ; i++, iVector++)
        cout << *iVector  << "  ";

    // Initialize the iterator the first element"
    iVector=Vector.begin();
    cout << "\n\nAdvance to the 3rd element." << endl;
    advance( iVector, 2);
    cout << "The element is " << *iVector << endl;
    dTheDiff = distance( Vector.begin(), iVector);
    cout << "The distance from the beginning is " << dTheDiff << endl;

    cout << "Calculate it in reverse order " << endl;
    dTheDiff = distance( iVector, Vector.begin());
    cout << "The distance is " << dTheDiff << endl;

    cout << "\nUse distance() to count from the 3rd element to the end."
         << endl;
    dTheDiff = distance( iVector, Vector.end());

    // Note that end() returns one past the end of the sequence
    cout << "The distance is " << dTheDiff << endl;

    cout <<"\nUse distance() to count the total length." << endl;
    dTheDiff = distance( Vector.begin(), Vector.end() );
    cout << "The total distance is " << dTheDiff << endl;
}

Program Output is:

The list is: A1  B2  C3  D4  E5  F6  G7

Advance to the 3rd element.
The element is C3
The distance from the beginning is 2
Calculate it in reverse order
The distance is -2

Use distance() to count from the 3rd element to the end.
The distance is 5

Use distance() to count the total length.
The total distance is 7


exp, log, and log10 (Sample)

The sample code below illustrates how to use the exp, log, and log10 STL functions in Visual C++.

Required Header:
<valarray>

Prototype:

 // exp
template<class T>
     valarray<T> exp(const valarray<T>& x);

 // log
template<class T>
     valarray<T> log(const valarray<T>& x);

// log10
template<class T>
     valarray<T> log10(const valarray<T>& x);

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
This article illustrates the use of the STL exp(), log(), and log10() functions through sample code.

Sample Code:

//////////////////////////////////////////////////////////////////////
//
// Compile options needed: None
//
// <filename> :  main.cpp
//
// Functions:
//
//    exp, log, log10
//////////////////////////////////////////////////////////////////////

#include <iostream>                 // for i/o functions
#include <valarray>                 // for valarray
#include <math.h>                   // for exp(), log(), and log10()

using namespace std;

#define ARRAY_SIZE  3               // array size

typedef valarray<double> DB_VARRAY;

void main()
{
    // Set val_array to contain values 1, 10, 100 for the following test.
    DB_VARRAY val_array(ARRAY_SIZE);
    for (int i = 0; i < ARRAY_SIZE; i++)
        val_array[i] = pow(10, i);

    // Display the size of val_array.
    cout << "Size of val_array = " << val_array.size() << "\r\n";

    // Display the content of val_array before calling exp, log, and
    // log10 functions.
    cout << "The values in val_array:\r\n";
    for (i = 0; i < ARRAY_SIZE; i++)
        cout << val_array[i] << "    ";
    cout << "\r\n\r\n";

    // rvalue_array to hold the return value from calling the sqrt() and
    // pow() functions.
    DB_VARRAY rvalue_array;

    // ----------------------------------------------------------------
    // exp() - display the content of rvalue_array
    // ----------------------------------------------------------------
    rvalue_array = exp(val_array);
    cout << "The result after calling exp():\r\n";
    for (i = 0; i < ARRAY_SIZE; i++)
        cout << rvalue_array[i] << "     ";
    cout << "\r\n\r\n";

    // ----------------------------------------------------------------
    // log() - display the content of rvalue_array
    // ----------------------------------------------------------------
    rvalue_array = log(val_array);
    cout << "The result after calling log():\r\n";
    for (i = 0; i < ARRAY_SIZE; i++)
        cout << rvalue_array[i] << "     ";
    cout << "\r\n\r\n";

    // ----------------------------------------------------------------
    // log10() - display the content of rvalue_array
    // ----------------------------------------------------------------
    rvalue_array = log10(val_array);
    cout << "The result after calling log10():\r\n";
    for (i = 0; i < ARRAY_SIZE; i++)
        cout << rvalue_array[i] << "     ";
    cout << "\r\n\r\n";
}

Program Output is:

Size of val_array = 3

The values in val_array:

1    10    100

The result after calling exp():

2.71828     22026.5     2.68812e+043

The result after calling log():

0     2.30259     4.60517

The result after calling log10():

0     1     2


find (STL Sample)

The sample code below illustrates how to use the find STL function in Visual C++.

Required Header:
<algorithm>

Prototype:

template<class InputIterator, class T> inline
     InputIterator find(InputIterator first, InputIterator last, const T& value)

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
The find algorithm locates the first element in the range [first, last) that matches value and returns the iterator positioned at the first matching element, or last + 1 if no such element exists.

Sample Code:

//////////////////////////////////////////////////////////////////////
//
// Compile options needed: /GX
//
// find.cpp : Illustrates how to use the find function.
//
// Functions:
//
//   find  - Find the first element in a sequence that matches value.
//////////////////////////////////////////////////////////////////////

// disable warning C4786: symbol greater than 255 character,
// okay to ignore
#pragma warning(disable: 4786)

#include <algorithm>
#include <iostream>

using namespace std;

void main()
{
    const int ARRAY_SIZE = 8 ;
    int IntArray[ARRAY_SIZE] = { 1, 2, 3, 4, 4, 5, 6, 7 } ;

    int *location ;   // stores the position of the first
                      // matching element.

    int i ;

    int value = 4 ;

    // print content of IntArray
    cout << "IntArray { " ;
    for(i = 0; i < ARRAY_SIZE; i++)
        cout << IntArray[i] << ", " ;
    cout << " }" << endl ;

    // Find the first element in the range [first, last + 1)
    // that matches value.
    location = find(IntArray, IntArray + ARRAY_SIZE, value) ;

    //print the matching element if any was found
    if (location != IntArray + ARRAY_SIZE)  // matching element found
        cout << "First element that matches " << value
             << " is at location " << location - IntArray << endl;
    else                                    // no matching element was
                                            // found
        cout << "The sequence does not contain any elements"
             << " with value " << value << endl ;
    }

Program Output is:

IntArray { 1, 2, 3, 4, 4, 5, 6, 7,  }

First element that matches 4 is at location 3


find_if (STL Sample)

The sample code below illustrates how to use the find_if STL function in Visual C++.

Required Header:
<algorithm>

Prototype:

template<class InputIterator, class T, class Predicate> inline
     InputIterator find_if(InputIterator first, InputIterator last, Predicate predicate)

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
The find_if algorithm locates the first element in the range [first, last) that causes the predicate to return true and returns the iterator positioned at that element, or last if no such element was found.

Sample Code:

//////////////////////////////////////////////////////////////////////
//
// Compile options needed: /GX
//
// findif.cpp : Illustrates how to use the find_if function.
//
// Functions:
//
//   find_if  - locate the first element in a range that satisfies
//              a predicate.
//////////////////////////////////////////////////////////////////////

// disable warning C4786: symbol greater than 255 character,
// okay to ignore
#pragma warning(disable: 4786)

#include <algorithm>
#include <iostream>

using namespace std;

// returns true if n is an odd number
int IsOdd( int n)
{
    return n % 2 ;
}

void main()
{
    const int ARRAY_SIZE = 8 ;
    int IntArray[ARRAY_SIZE] = { 1, 2, 3, 4, 4, 5, 6, 7 } ;
    int *location ;   // stores the position of the first
                      // element that is an odd number
    int i ;

        // print content of IntArray
    cout << "IntArray { " ;
    for(i = 0; i < ARRAY_SIZE; i++)
        cout << IntArray[i] << ", " ;
    cout << " }" << endl ;

    // Find the first element in the range [first, last -1 ]
    // that is an odd number
    location = find_if(IntArray, IntArray + ARRAY_SIZE, IsOdd) ;

    //print the location of the first element
    // that is an odd number
    if (location != IntArray + ARRAY_SIZE)  // first odd element found
        cout << "First odd element " << *location
             << " is at location " << location - IntArray << endl;
    else         // no odd numbers in the range
        cout << "The sequence does not contain any odd numbers"
             << endl ;
    }

Program Output is:

IntArray { 1, 2, 3, 4, 4, 5, 6, 7,  }

First odd element 1 is at location 0


for_each (STL Sample)

The sample code below illustrates how to use the for_each STL function in Visual C++.

Required Header:
<algorithm>

Prototype:

template<class InputIterator, class Function> inline
     Function for_each(InputIterator first, InputIterator last, Function F)

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
The for_each algorithm calls Function F for each element in the range [first, last) and returns the input parameter F. This function does not modify any elements in the sequence.

Sample Code:

//////////////////////////////////////////////////////////////////////
//
// Compile options needed: /GX
//
// count.cpp : Illustrates how to use the for_each function.
//
// Functions:
//
//   for_each  - Calls function F for every element in a range.
//
//   begin     - Returns an iterator that points to the first element
//               in a sequence.
//
//   end       - Returns an iterator that points one past the end of
//               a sequence.
//////////////////////////////////////////////////////////////////////

// disable warning C4786: symbol greater than 255 character,
// okay to ignore
#pragma warning(disable: 4786)

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

// prints the cube of integer n
void PrintCube(int n)
{
    cout << n * n * n << " " ;
}

void main()
{
    const int VECTOR_SIZE = 8 ;

    // Define a template class vector of integers
    typedef vector<int > IntVector ;

    //Define an iterator for template class vector of integer
    typedef IntVector::iterator IntVectorIt ;

    IntVector Numbers(VECTOR_SIZE) ;   //vector containing numbers

    IntVectorIt start, end, it ;

    int i ;

    // Initialize vector Numbers
    for (i = 0; i < VECTOR_SIZE; i++)
        Numbers[i] = i + 1 ;

    start = Numbers.begin() ;   // location of first
                                // element of Numbers

    end = Numbers.end() ;       // one past the location
                                // last element of Numbers

    // print content of Numbers
    cout << "Numbers { " ;
    for(it = start; it != end; it++)
        cout << *it << " " ;
    cout << " }\n" << endl ;

    // for each element in the range [first, last)
    // print the cube of the element
    for_each(start, end, PrintCube) ;
    cout << "\n\n" ;
}

Program Output is:

Numbers { 1 2 3 4 5 6 7 8  }

1 8 27 64 125 216 343 512


Generate (STL Sample)

The sample code below illustrates how to use the Generate STL function in Visual C++.

Required Header:
<algorithm>

Prototype:

template<class InputIterator, class Function> inline
     Function for_each(InputIterator first, InputIterator last, Function F)

template<class ForwardIterator, class Generator> inline
     void generate(ForwardIterator first, ForwardIterator last, Generator gen)

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
The Generate algorithm traverses the range [first, last + 1), assigning to each element the value returned by gen. Generate modifies the elements in the specified range.

Sample Code:

//////////////////////////////////////////////////////////////////////
//
// Compile options needed: /GX
//
// generate.cpp : Illustrates how to use the generate function.
//
// Functions:
//
//   generate - Fill a sequence using a generator function
//   Fibonacci - return the next Fibonacci number in the
//               Fibonacci series.
//////////////////////////////////////////////////////////////////////

// disable warning C4786: symbol greater than 255 character,
// okay to ignore
#pragma warning(disable: 4786)

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

// return the next Fibonacci number in the
// Fibonacci series.
int Fibonacci(void)
{
    static int r;
    static int f1 = 0;
    static int f2 = 1;
    r = f1 + f2 ;
    f1 = f2 ;
    f2 = r ;
    return f1 ;
}

void main()
{
    const int VECTOR_SIZE = 8 ;

    // Define a template class vector of integers
    typedef vector<int > IntVector ;

    //Define an iterator for template class vector of integer
    typedef IntVector::iterator IntVectorIt ;

    IntVector Numbers(VECTOR_SIZE) ;   //vector containing numbers

    IntVectorIt start, end, it ;

    start = Numbers.begin() ;   // location of first
                                // element of Numbers

    end = Numbers.end() ;       // one past the location
                                // last element of Numbers

    // fill the range [first, last +1) with a series of
    // Fibonnaci numbers using the Fibonacci function
    generate(start, end, Fibonacci) ;

    // print content of Numbers
    cout << "Numbers { " ;
    for(it = start; it != end; it++)
        cout << *it << " " ;
    cout << " }\n" << endl ;
}

Program Output is:

Numbers { 1 1 2 3 5 8 13 21  }


generate_n (STL Sample)

The sample code below illustrates how to use the generate_n STL function in Visual C++.

Required Header:
<algorithm>

Prototype:

template<class OutputIterator, class Size, class Generator> inline
     void generate_n(OutputIterator first, Size n, Generator gen)

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
The generate_n algorithm traverses the range [first, first + n), assigning to each element the value returned by gen. Note that generate modifies the elements in the specified range.

Sample Code:

//////////////////////////////////////////////////////////////////////
//
// Compile options needed: /GX
//
// generate_n.cpp : Illustrates how to use the generate_n function.
//
// Functions:
//
//   generate_n  - Fill a specified number of elements of a sequence
//                 using a generator function.
//
//   begin       - Returns an iterator that points to the first element
//                 in a sequence.
//
//   end         - Returns an iterator that points one past the end of
//                 a sequence.
//
//   size        - Returns the length of a sequence.
//////////////////////////////////////////////////////////////////////

// disable warning C4786: symbol greater than 255 character,
// okay to ignore
#pragma warning(disable: 4786)

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

// return the next Fibonacci number in the
// Fibonacci series.
int Fibonacci(void)
{
    static int r;
    static int f1 = 0;
    static int f2 = 1;
    r = f1 + f2 ;
    f1 = f2 ;
    f2 = r ;
    return f1 ;
}

void main()
{
    const int VECTOR_SIZE = 15 ;

    // Define a template class vector of integers
    typedef vector<int > IntVector ;

    //Define an iterator for template class vector of integer
    typedef IntVector::iterator IntVectorIt ;

    IntVector Numbers(VECTOR_SIZE) ;   //vector containing numbers

    IntVectorIt start, end, it ;

    int i ;

    //Initialize vector Numbers
    for(i = 0; i < VECTOR_SIZE; i++)
        Numbers[i] = i * i ;

    start = Numbers.begin() ;   // location of first
                                // element of Numbers

    end = Numbers.end() ;       // one past the location
                                // last element of Numbers

    cout << "Before calling generate_n" << endl ;

    // print content of Numbers
    cout << "Numbers { " ;
    for(it = start; it != end; it++)
        cout << *it << " " ;
    cout << " }\n" << endl ;

    // fill the specified range with a series of
    // Fibonacci numbers using the Fibonacci function
    generate_n(start + 5, Numbers.size() - 5, Fibonacci) ;

    cout << "After calling generate_n" << endl ;

    // print content of Numbers
    cout << "Numbers { " ;
    for(it = start; it != end; it++)
        cout << *it << " " ;
    cout << " }\n" << endl ;
}

Program Output is:

Before calling generate_n
Numbers { 0 1 4 9 16 25 36 49 64 81 100 121 144 169 196  }

After calling generate_n
Numbers { 0 1 4 9 16 1 1 2 3 5 8 13 21 34 55  }


heap (STL Sample)

The sample code below illustrates how to use the heap STL function in Visual C++.

Required Header:
<algorithm>

Prototype:

template<class RandomAccessIterator> inline
     void make_heap(RandomAccessIterator first, RandomAccessIterator last)

template<class RandomAccessIterator> inline
     void sort_heap(RandomAccessIterator first, RandomAccessIterator last)

template<class RandomAccessIterator> inline
     void push_heap(RandomAccessIterator first, RandomAccessIterator last)

template<class RandomAccessIterator> inline
     void pop_heap(RandomAccessIterator first, RandomAccessIterator last)

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
A heap is a sequence of elements organized like a binary tree. Each heap element corresponds to a tree node. The first value in the sequence [first..last) is the root, and is the largest value in the heap. Every element in the heap satisfies the following: Every element is less than or equal to its parent. The largest element is stored in the root, and all children hold progressively smaller values. The make_heap function converts the range [first..last) into a heap. The sort_heap function sorts a "heapified" sequence that was created using the make_heap function. The push_heap function inserts a new value into the heap. The pop_heap function swaps the first and last elements in the heap specified by [first, last), then reduces the length of the sequence by one before restoring the heap property. The non-predicate versions of the heap functions use the operator< for comparisons.

Sample Code:

//////////////////////////////////////////////////////////////////////
//
// Compile options needed: /GX
//
// heap_functions.cpp : Illustrates how to use the
//                      make_heap, sort_heap, push_heap
//                      and pop_heap functions.
//
// Functions:
//
//    make_heap : convert a sequence to a heap
//    sort_heap : sort a heap
//    push_heap : insert an element in a heap
//    pop_heap  : remove the top element from a heap
//////////////////////////////////////////////////////////////////////

// disable warning C4786: symbol greater than 255 character,
// okay to ignore
#pragma warning(disable: 4786)

#include <iostream>
#include <algorithm>
#include <functional>
#include <vector>

using namespace std;

void main()
{
    const int VECTOR_SIZE = 8 ;

    // Define a template class vector of int
    typedef vector<int > IntVector ;

    //Define an iterator for template class vector of strings
    typedef IntVector::iterator IntVectorIt ;

    IntVector Numbers(VECTOR_SIZE) ;

    IntVectorIt it ;

    // Initialize vector Numbers
    Numbers[0] = 4 ;
    Numbers[1] = 10;
    Numbers[2] = 70 ;
    Numbers[3] = 10 ;
    Numbers[4] = 30 ;
    Numbers[5] = 69 ;
    Numbers[6] = 96 ;
    Numbers[7] = 100;

    // print content of Numbers
    cout << "Numbers { " ;
    for(it = Numbers.begin(); it != Numbers.end(); it++)
        cout << *it << " " ;
    cout << " }\n" << endl ;

    // convert Numbers into a heap
    make_heap(Numbers.begin(), Numbers.end()) ;

    cout << "After calling make_heap\n" << endl ;

    // print content of Numbers
    cout << "Numbers { " ;
    for(it = Numbers.begin(); it != Numbers.end(); it++)
        cout << *it << " " ;
    cout << " }\n" << endl ;

    // sort the heapified sequence Numbers
    sort_heap(Numbers.begin(), Numbers.end()) ;

    cout << "After calling sort_heap\n" << endl ;

    // print content of Numbers
    cout << "Numbers { " ;
    for(it = Numbers.begin(); it != Numbers.end(); it++)
        cout << *it << " " ;
    cout << " }\n" << endl ;

    //insert an element in the heap
    Numbers.push_back(7) ;
    push_heap(Numbers.begin(), Numbers.end()) ;

    // you need to call make_heap to re-assert the
    // heap property
    make_heap(Numbers.begin(), Numbers.end()) ;

    cout << "After calling push_heap and make_heap\n" << endl ;

    // print content of Numbers
    cout << "Numbers { " ;
    for(it = Numbers.begin(); it != Numbers.end(); it++)
        cout << *it << " " ;
    cout << " }\n" << endl ;

    // remove the root element from the heap Numbers
    pop_heap(Numbers.begin(), Numbers.end()) ;

    cout << "After calling pop_heap\n" << endl ;

    // print content of Numbers
    cout << "Numbers { " ;
    for(it = Numbers.begin(); it != Numbers.end(); it++)
        cout << *it << " " ;
    cout << " }\n" << endl ;
}

Program Output is:

Numbers { 4 10 70 10 30 69 96 100  }

After calling make_heap

Numbers { 100 30 96 10 4 69 70 10  }

After calling sort_heap

Numbers { 4 10 10 30 69 70 96 100  }

After calling push_heap and make_heap

Numbers { 100 69 96 30 4 70 10 10 7  }

After calling pop_heap

Numbers { 96 69 70 30 4 7 10 10 100  }


The Predicate Versions of heap (STL Sample)

The sample code below illustrates how to use the predicate versions of the heap STL function in Visual C++.

Required Header:
<algorithm>

Prototype:

template<class RandomAccessIterator, class Compare> inline
     void make_heap(RandomAccessIterator first, RandomAccessIterator last, Compare compare)

template<class RandomAccessIterator, class Compare> inline
     void sort_heap(RandomAccessIterator first, RandomAccessIterator last, Compare compare)

template<class RandomAccessIterator, class Compare> inline
     void push_heap(RandomAccessIterator first, RandomAccessIterator last, Compare compare)

template<class RandomAccessIterator, class Compare> inline
     void pop_heap(RandomAccessIterator first, RandomAccessIterator last, Compare compare)

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
A heap is a sequence of elements organized like a binary tree. Each heap element corresponds to a tree node. The first value in the sequence [first..last) is the root, and is ordered by the predicate. For example, if the predicate is greater, every element in the heap satisfies the following: Every element is greater than or equal to its parent. The smallest element is stored in the root, and all children hold progressively larger values. The make_heap function converts the range [first..last) into a heap. The sort_heap function sorts a "heapified" sequence that was created using the make_heap function. The push_heap function inserts a new value into the heap. The pop_heap function swaps the first and last elements in the heap specified by [first, last), then reduces the length of the sequence by one before restoring the heap property. The predicate versions of the heap functions use the compare function for comparisons.

Sample Code:

//////////////////////////////////////////////////////////////////////
//
// Compile options needed: /GX
//
// heap_functions.cpp : Illustrates how to use the predicate versions
//                      of the make_heap, sort_heap, push_heap
//                      and pop_heap functions.
//
// Functions:
//
//    make_heap : Convert a sequence to a heap.
//    sort_heap : Sort a heap.
//    push_heap : Insert an element in a heap.
//    pop_heap  : Remove the top element from a heap.
//////////////////////////////////////////////////////////////////////

// disable warning C4786: symbol greater than 255 character,
// okay to ignore
#pragma warning(disable: 4786)

#include <iostream>
#include <algorithm>
#include <functional>
#include <vector>

using namespace std;

void main()
{
   const int VECTOR_SIZE = 8 ;

   // Define a template class vector of int
   typedef vector<int > IntVector ;

   //Define an iterator for template class vector of strings
   typedef IntVector::iterator IntVectorIt ;

   IntVector Numbers(VECTOR_SIZE) ;
   IntVectorIt it ;

   // Initialize vector Numbers
   Numbers[0] = 4 ;
   Numbers[1] = 10;
   Numbers[2] = 70 ;
   Numbers[3] = 10 ;
   Numbers[4] = 30 ;
   Numbers[5] = 69 ;
   Numbers[6] = 96 ;
   Numbers[7] = 100;

   // print content of Numbers
   cout << "Numbers { " ;
   for(it = Numbers.begin(); it != Numbers.end(); it++)
      cout << *it << " " ;
   cout << " }\n" << endl ;

   // convert Numbers into a heap
   make_heap(Numbers.begin(), Numbers.end(), greater<int>()) ;
   cout << "After calling make_heap\n" << endl ;

   // print content of Numbers
   cout << "Numbers { " ;
   for(it = Numbers.begin(); it != Numbers.end(); it++)
      cout << *it << " " ;
   cout << " }\n" << endl ;

   // sort the heapified sequence Numbers
   sort_heap(Numbers.begin(), Numbers.end(), greater<int>()) ;
   cout << "After calling sort_heap\n" << endl ;

   // print content of Numbers
   cout << "Numbers { " ;
   for(it = Numbers.begin(); it != Numbers.end(); it++)
      cout << *it << " " ;
   cout << " }\n" << endl ;

   make_heap(Numbers.begin(), Numbers.end(), greater<int>()) ;
   //insert an element in the heap
   Numbers.push_back(7) ;
   push_heap(Numbers.begin(), Numbers.end(), greater<int>()) ;
   cout << "After calling push_heap()\n" << endl;

   // print content of Numbers
   cout << "Numbers { " ;
   for(it = Numbers.begin(); it != Numbers.end(); it++)
      cout << *it << " " ;
   cout << " }\n" << endl ;

   //remove the root element from the heap Numbers
   pop_heap(Numbers.begin(), Numbers.end(), greater<int>()) ;
   cout << "After calling pop_heap\n" << endl ;

   // print content of Numbers
   cout << "Numbers { " ;
   for(it = Numbers.begin(); it != Numbers.end(); it++)
      cout << *it << " " ;
   cout << " }\n" << endl ;
}

Program Output is:

Numbers { 4 10 70 10 30 69 96 100  }

After calling make_heap
Numbers { 4 10 69 10 30 70 96 100  }

After calling sort_heap
Numbers { 100 96 70 69 30 10 10 4  }

After calling push_heap()
Numbers { 4 7 10 30 100 10 70 96 69  }

After calling pop_heap
Numbers { 7 30 10 69 100 10 70 96 4  }


includes (STL Sample)

The sample code below illustrates how to use the includes STL function in Visual C++.

Required Header:
<algorithm>

Prototype:

template<class InputIterator1, class InputIterator2>
     inline bool includes(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2)

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
The includes algorithm searches for one sequence of values in another sequence of values. includes returns true if every element in the range [first2..last2) is in the sequence [first1..last1). This version of includes assumes that both sequences are sorted using operator<.

Sample Code:

//////////////////////////////////////////////////////////////////////
//
// Compile options needed: /GX
//
// includesP.cpp : Illustrates how to use the includes function.
//
// Functions:
//
//    includes - Search for one sequence in another.
//////////////////////////////////////////////////////////////////////

// disable warning C4786: symbol greater than 255 character,
// okay to ignore
#pragma warning(disable: 4786)

#include <iostream>
#include <algorithm>
#include <functional>
#include <string>
#include <vector>
#include <deque>

using namespace std;

void main()
{
    const int VECTOR_SIZE = 5 ;

    // Define a template class vector of strings
    typedef vector<string > StringVector ;

    //Define an iterator for template class vector of strings
    typedef StringVector::iterator StringVectorIt ;

    // Define a template class deque of strings
    typedef deque<string > StringDeque ;

    //Define an iterator for template class deque of strings
    typedef StringDeque::iterator StringDequeIt ;

    StringVector CartoonVector(VECTOR_SIZE) ;
    StringDeque CartoonDeque ;

    StringVectorIt start1, end1, it1 ;
    StringDequeIt start2, end2, it2 ;

    // Initialize vector Vector1
    CartoonVector[0] = "Aladdin" ;
    CartoonVector[1] = "Jasmine" ;
    CartoonVector[2] = "Mickey" ;
    CartoonVector[3] = "Minnie" ;
    CartoonVector[4] = "Goofy" ;

    start1 = CartoonVector.begin() ;  // location of first
                                      // element of CartoonVector

    end1 = CartoonVector.end() ;  // one past the location last
                                  // element of CartoonVector

    //Initialize list CartoonDeque
    CartoonDeque.push_back("Jasmine") ;
    CartoonDeque.push_back("Aladdin") ;
    CartoonDeque.push_back("Goofy") ;

    start2 = CartoonDeque.begin() ; // location of first
                                    // element of CartoonDeque

    end2 = CartoonDeque.end() ; // one past the location last
                                // element of CartoonDeque

    //sort CartoonVector and CartoonDeque alphabetically
    //includes requires the sequences
    //to be sorted.
    sort(start1, end1) ;
    sort(start2, end2) ;

    // print contents of CartoonVector and CartoonDeque
    cout << "CartoonVector { " ;
    for(it1 = start1; it1 != end1; it1++)
        cout << *it1 << ", " ;
    cout << " }\n" << endl ;
    cout << "CartoonDeque { " ;
    for(it2 = start2; it2 != end2; it2++)
        cout << *it2 << ", " ;
    cout << " }\n" << endl ;

    //Is CartoonDeque a subset of CartoonVector?
    if(includes(start1, end1, start2, end2) )
        cout << "CartoonVector includes CartoonDeque"
        << endl ;
    else
        cout << "CartoonVector does not include CartoonDeque"
        << endl ;

}

Program Output is:

CartoonVector { Aladdin, Goofy, Jasmine, Mickey, Minnie,  }

CartoonDeque { Aladdin, Goofy, Jasmine,  }

CartoonVector includes CartoonDeque


Predicate Version of includes (STL Sample)

The sample code below illustrates how to use the predicate version of the includes STL function in Visual C++.

Required Header:
<algorithm>

Prototype:

template<class InputIterator1, class InputIterator2, class Compare>
     inline bool includes(InputIterator1 first1,
     InputIterator1 last1,
     InputIterator2 first2,
     InputIterator2 last2,
     Compare compare)

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
The includes algorithm searches for one sequence of values in another sequence of values. includes returns true if every element in the range [first2..last2) is in the sequence [first1..last1). This version of includes assumes that both sequences are sorted using the compare function.

Sample Code:

//////////////////////////////////////////////////////////////////////
//
// Compile options needed: /GX
//
// includesP.cpp : Illustrates how to use the predicate version of
//                 includes function.
//
// Functions:
//
//    includes - Search for one sequence in another.
//    string_compare - Compare strings, return true if
//                       s1 < s2.
//////////////////////////////////////////////////////////////////////

// disable warning C4786: symbol greater than 255 character,
// okay to ignore
#pragma warning(disable: 4786)

#include <iostream>
#include <algorithm>
#include <functional>
#include <string>
#include <vector>
#include <deque>

using namespace std ;

bool string_compare(const string& s1, const string& s2)
{
    return s1 < s2 ? 1 : 0;
}
void main()
{
    const int VECTOR_SIZE = 5 ;

    // Define a template class vector of strings
    typedef vector<string> StringVector ;

    //Define an iterator for template class vector of strings
    typedef StringVector::iterator StringVectorIt ;

    // Define a template class deque of strings
    typedef deque<string> StringDeque ;

    //Define an iterator for template class deque of strings
    typedef StringDeque::iterator StringDequeIt ;

    StringVector CartoonVector(VECTOR_SIZE) ;
    StringDeque CartoonDeque ;

    StringVectorIt start1, end1, it1 ;
    StringDequeIt start2, end2, it2 ;

    // Initialize vector Vector1
    CartoonVector[0] = "Aladdin" ;
    CartoonVector[1] = "Jasmine" ;
    CartoonVector[2] = "Mickey" ;
    CartoonVector[3] = "Minnie" ;
    CartoonVector[4] = "Goofy" ;

    start1 = CartoonVector.begin() ;  // location of first
                                      // element of CartoonVector

    end1 = CartoonVector.end() ;  // one past the location last
                                  // element of CartoonVector

    //Initialize list CartoonDeque
    CartoonDeque.push_back("Jasmine") ;
    CartoonDeque.push_back("Aladdin") ;
    CartoonDeque.push_back("Goofy") ;

    start2 = CartoonDeque.begin() ; // location of first
                                    // element of CartoonDeque

    end2 = CartoonDeque.end() ; // one past the location last
                                // element of CartoonDeque

    //sort CartoonVector and CartoonDeque alphabetically
    //includes requires the sequences
    //to be sorted.
    sort(start1, end1, string_compare) ;
    sort(start2, end2, string_compare) ;

    // print contents of CartoonVector and CartoonDeque
    cout << "CartoonVector { " ;
    for(it1 = start1; it1 != end1; it1++)
        cout << *it1 << ", " ;
    cout << " }\n" << endl ;
    cout << "CartoonDeque { " ;
    for(it2 = start2; it2 != end2; it2++)
        cout << *it2 << ", " ;
    cout << " }\n" << endl ;

    //Is CartoonDeque a subset of CartoonVector?
    if(includes(start1, end1, start2, end2, string_compare) )
        cout << "CartoonVector includes CartoonDeque"
        << endl ;
    else
        cout << "CartoonVector does not include CartoonDeque"
        << endl ;

}

Program Output is:

CartoonVector { Aladdin, Goofy, Jasmine, Mickey, Minnie,  }

CartoonDeque { Aladdin, Goofy, Jasmine,  }

CartoonVector includes CartoonDeque


inner_product (STL Sample)

The sample code below illustrates how to use the inner_product STL function in Visual C++.

Required Header:
<numeric>

Prototype:

template<class InputIterator1, class InputIterator2, class T>
     inline T inner_product(InputIterator first, InputIterator last, InputIterator first2, T init)

template<class InputIterator1, class InputIterator2, class T, class BinOp1, class BinOp2>
     inline T inner_product(InputIterator1 first, InputIterator1 last, InputIterator2 first2,
     T init, BinOp1 binary_op1, BinOp2 binary_op2)

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
inner_product computes its result by initializing the accumulator acc with init and then modifying it with: acc = acc + (*i1) * (*i2) - or - acc = binary_op1(acc, binary_op2(*i1, *i2)) for every iterator i1 in the range [first, last) and iterator i2 in the range [first2, first2 + (last - first)) in order.

Sample Code:

///////////////////////////////////////////////////////////////////////
//
// Compile options needed: /GX
//
// inner_product.cpp : Demonstrates the use of inner_product().
//
// Description of
//         inner_product(first,last,first2,init)
//         inner_product(first,last,first2,init,binary_op1,binary_op2):
//
//    Computes its result by initializing the accumulator acc with init
//        acc = init
//    and then modifying it with
//        acc = acc  +  (*i1) * (*i2)
//    or
//        acc = binary_op1(acc, binary_op2(*i1, *i2))
//    for every iterator i1 in the range [first, last) and
//    iterator  i2  in  the  range [first2, first2 + (last - first))
//    in order.
///////////////////////////////////////////////////////////////////////

#include <iostream>
#include <numeric>
#include <functional>
#include <vector>
#include <iterator>

using namespace std;

typedef vector < float > FloatArray;
typedef ostream_iterator < float, char, char_traits<char> >
FloatOstreamIt;

void main ()
{
    FloatOstreamIt itOstream(cout," ");

    // Initialize the arrays
    FloatArray rgF1, rgF2;
    for (int i=1; i<=5; i++) {
        rgF1.push_back(i);
        rgF2.push_back(i*i);
    };

    // Print the arrays
    cout << "Array 1: ";
    copy(rgF1.begin(),rgF1.end(),itOstream);
    cout << endl;
    cout << "Array 2: ";
    copy(rgF2.begin(),rgF2.end(),itOstream);
    cout << endl;

    // Compute the inner_product of the arrays.  This is the
    // sum of the products (S.O.P) of the corresponding elements
    float ip1 = inner_product(rgF1.begin(),rgF1.end(),rgF2.begin(),0);
    cout << "The inner product (S.O.P) of Array1 and Array2 is "
       << ip1
       << endl;

    // Compute the inner_product of the arrays.  This is the
    // product of the sums (P.O.S.) of the corresponding elements
    float ip2 = inner_product(rgF1.begin(),rgF1.end(),rgF2.begin(),1,
                            multiplies<float>(),plus<float>());
    cout << "The inner product (P.O.S.) of Array1 and Array2 is "
       << ip2
       << endl;
}

Program Output is:

Array 1: 1 2 3 4 5
Array 2: 1 4 9 16 25
The inner product (S.O.P) of Array1 and Array2 is 225
The inner product (P.O.S.) of Array1 and Array2 is 86400


inplace_merge (STL Sample)

The sample code below illustrates how to use the inplace_merge STL function in Visual C++.

Required Header:
<algorithm>

Prototype:

template<class BidirectionalIterator>
     inline void inplace_merge(BidirectionalIterator first, BidirectionalIterator middle, BidirectionalIterator last)

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
The inplace_merge algorithm merges two sorted sub-sequences: [first..middle) and [middle..last) in place into a single sorted sequence [first..last). This version assumes that the ranges [first..middle) and [middle..last) are sorted using operator<. If both ranges contain equal values, the value from the first range will be stored first.

Sample Code:

//////////////////////////////////////////////////////////////////////
//
// Compile options needed: /GX
//
// inplace_merge.cpp : Illustrates how to use the inplace_merge
//                     function.
//
// Functions:
//
//   inplace_merge : Merge two sorted sub-sequences in place into a
//                   single sorted list.
//
//   begin - Returns an iterator that points to the first element in a
//           sequence.
//
//   end - Returns an iterator that points one past the end of a sequence.
//////////////////////////////////////////////////////////////////////

// disable warning C4786: symbol greater than 255 character,
// okay to ignore
#pragma warning(disable: 4786)

#include <iostream>
#include <algorithm>
#include <functional>
#include <vector>

using namespace std;

void main()
{
    const int VECTOR_SIZE = 8 ;

    // Define a template class vector of int
    typedef vector<int > IntVector ;

    //Define an iterator for template class vector of strings
    typedef IntVector::iterator IntVectorIt ;

    IntVector Numbers(VECTOR_SIZE) ;

    IntVectorIt start, end, it ;

    // Initialize vector Numbers
    Numbers[0] = 4 ;
    Numbers[1] = 10;
    Numbers[2] = 70 ;
    Numbers[3] = 10 ;
    Numbers[4] = 30 ;
    Numbers[5] = 69 ;
    Numbers[6] = 96 ;
    Numbers[7] = 100;

    start = Numbers.begin() ;   // location of first
                                // element of Numbers

    end = Numbers.end() ;       // one past the location
                                // last element of Numbers

    cout << "Before calling inplace_merge\n" << endl ;

    // print content of Numbers
    cout << "Numbers { " ;
    for(it = start; it != end; it++)
        cout << *it << " " ;
    cout << " }\n" << endl ;

    //merge the elements of Numbers in place
    inplace_merge(start, start + 3, end) ;

    cout << "After calling inplace_merge\n" << endl ;

    // print content of Numbers
    cout << "Numbers { " ;
    for(it = start; it != end; it++)
        cout << *it << " " ;
    cout << " }\n" << endl ;
}

Program Output is:

Before calling inplace_merge

Numbers { 4 10 70 10 30 69 96 100  }

After calling inplace_merge

Numbers { 4 10 10 30 69 70 96 100  }


Predicate Version of inplace_merge (STL Sample)

The sample code below illustrates how to use the predicate version of the inplace_merge STL function in Visual C++.

Required Header:
<algorithm>

Prototype:

template<class BidirectionalIterator, class Compare> inline
     void inplace_merge(BidirectionalIterator first, BidirectionalIterator middle,
     BidirectionalIterator last, Compare compare)

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
The inplace_merge algorithm merges two sorted sub-sequences: [first..middle) and [middle..last) in place into a single sorted sequence [first..last). This version assumes that the ranges [first..middle) and [middle..last) are sorted using the compare function. If both ranges contain equal values, the value from the first range will be stored first.

Sample Code:

//////////////////////////////////////////////////////////////////////
//
// Compile options needed: /GX
//
// inplace_mergeP.cpp : Illustrates how to use the predicate version of
//                      the inplace_merge function.
//
// Functions:
//
//    inplace_merge - Merge two sorted sub-sequences in place into a
//                    single sorted list using the compare function.
//
//    begin - Returns an iterator that points to the first element in a
//            sequence.

//    end - Returns an iterator that points one past the end of a sequence.
//////////////////////////////////////////////////////////////////////

// disable warning C4786: symbol greater than 255 character,
// okay to ignore
#pragma warning(disable: 4786)

#include <iostream>
#include <algorithm>
#include <functional>
#include <vector>

using namespace std;

void main()
{
    const int VECTOR_SIZE = 8 ;

    // Define a template class vector of int
    typedef vector<int > IntVector ;

    //Define an iterator for template class vector of strings
    typedef IntVector::iterator IntVectorIt ;

    IntVector Numbers(VECTOR_SIZE) ;

    IntVectorIt start, end, it ;

    // Initialize vector Numbers
    Numbers[0] = 4 ;
    Numbers[1] = 10;
    Numbers[2] = 70 ;
    Numbers[3] = 10 ;
    Numbers[4] = 30 ;
    Numbers[5] = 69 ;
    Numbers[6] = 96 ;
    Numbers[7] = 100;

    start = Numbers.begin() ;   // location of first
                                // element of Numbers

    end = Numbers.end() ;       // one past the location
                                // last element of Numbers

    cout << "Before calling inplace_merge\n" << endl ;

    // print content of Numbers
    cout << "Numbers { " ;
    for(it = start; it != end; it++)
        cout << *it << " " ;
    cout << " }\n" << endl ;

    //merge the elements of Numbers in place
    inplace_merge(start, start + 3, end, less<int>()) ;

    cout << "After calling inplace_merge\n" << endl ;

    // print content of Numbers
    cout << "Numbers { " ;
    for(it = start; it != end; it++)
        cout << *it << " " ;
    cout << " }\n" << endl ;
}

Program Output is:

Before calling inplace_merge

Numbers { 4 10 70 10 30 69 96 100  }

After calling inplace_merge

Numbers { 4 10 10 30 69 70 96 100  }


iter_swap (STL Sample)

The sample code below illustrates how to use the iter_swap STL function in Visual C++.

Required Header:
<algorithm>

Prototype:

template<class ForwardIterator1, class ForwardIterator2> inline
     void iter_swap(ForwardIterator1 first, ForwardIterator2 second)

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
The iter_swap algorithm swaps two elements represented by two iterators.

Sample Code:

//////////////////////////////////////////////////////////////////////
//
// Compile options needed: /GX
//
// iter_swap.cpp : Illustrates how to use the iter_swap function.
//
// Functions:
//
//   iter_swap  - Swap two elements in a sequence represented by
//                two iterators.
//
//   begin      - Returns an iterator that points to the first element
//                in a sequence.
//
//   end        - Returns an iterator that points one past the end of
//                  a sequence.
//////////////////////////////////////////////////////////////////////

// disable warning C4786: symbol greater than 255 character,
// okay to ignore
#pragma warning(disable: 4786)

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

// return the next Fibonacci number in the
// Fibonacci series.
int Fibonacci(void)
{
    static int r;
    static int f1 = 0;
    static int f2 = 1;
    r = f1 + f2 ;
    f1 = f2 ;
    f2 = r ;
    return f1 ;
}

void main()
{
    const int VECTOR_SIZE = 8 ;

    // Define a template class vector of integers
    typedef vector<int > IntVector ;

    //Define an iterator for template class vector of integer
    typedef IntVector::iterator IntVectorIt ;

    IntVector Numbers(VECTOR_SIZE) ;   //vector containing numbers

    IntVectorIt start, end, it ;

    start = Numbers.begin() ;   // location of first
                                // element of Numbers

    end = Numbers.end() ;       // one past the location
                                // last element of Numbers

    // fill the range [first, last +1) with a series of
    // Fibonacci numbers using the Fibonacci function
    generate(start, end, Fibonacci) ;

    cout << "Before calling iter_swap" << endl ;

    // print content of Numbers
    cout << "Numbers { " ;
    for(it = start; it != end; it++)
        cout << *it << " " ;
    cout << " }\n" << endl ;

    // swap the first and last elements of the
    // sequence using iter_swap
    iter_swap(start, end - 1) ;

    cout << "After calling iter_swap" << endl ;

    // print content of Numbers
    cout << "Numbers { " ;
    for(it = start; it != end; it++)
        cout << *it << " " ;
    cout << " }\n" << endl ;

}

Program Output is:

Before calling iter_swap
Numbers { 1 1 2 3 5 8 13 21  }

After calling iter_swap
Numbers { 21 1 2 3 5 8 13 1  }


list::assign (STL Sample)

The sample code below illustrates how to use the list::assign STL function in Visual C++.

Required Header:
<list>

Prototype:

     void assign(const_iterator first, const_iterator last);
     void assign(size_type n, const T& x = T());
     iterator erase(iterator it);
     iterator erase(iterator first, iterator last);
     bool empty() const;

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
The first member function replaces the sequence controlled by *this with the sequence [first, last). The second member function replaces the sequence controlled by *this with a repetition of n elements of value x. The third member function removes the element of the controlled sequence pointed to by it. The fourth member function removes the elements of the controlled sequence in the range [first, last). Both return an iterator that designates the first element remaining beyond any elements removed, or end() if no such element exists. The last member function returns true for an empty controlled sequence.

Sample Code:

//////////////////////////////////////////////////////////////////////
//
// Compile options needed: -GX
//
// assign.cpp :  Shows the various ways to assign and erase elements
//               from a list<T>.
//
// Functions:
//
//    list::assign
//    list::empty
//    list::erase
//////////////////////////////////////////////////////////////////////

#include <list>
#include <iostream>

using namespace std ;

typedef list<int> LISTINT;

void main()
{
    LISTINT listOne;
    LISTINT listAnother;
    LISTINT::iterator i;

    // Add some data
    listOne.push_front (2);
    listOne.push_front (1);
    listOne.push_back (3);

    listAnother.push_front(4);

    listAnother.assign(listOne.begin(), listOne.end());

    // 1 2 3
    for (i = listAnother.begin(); i != listAnother.end(); ++i)
        cout << *i << " ";
    cout << endl;

    listAnother.assign(4, 1);

    // 1 1 1 1
    for (i = listAnother.begin(); i != listAnother.end(); ++i)
        cout << *i << " ";
    cout << endl;

    listAnother.erase(listAnother.begin());

    // 1 1 1
    for (i = listAnother.begin(); i != listAnother.end(); ++i)
        cout << *i << " ";
    cout << endl;

    listAnother.erase(listAnother.begin(), listAnother.end());
    if (listAnother.empty())
        cout << "All gone\n";
}

Program Output is:

1 2 3
1 1 1 1
1 1 1
All gone


list::back, list::front (STL Sample)

The sample code below illustrates how to use the list::back and list::front STL functions in Visual C++.

Required Header:
<list>

Prototype:

     reference back();
     const_reference back() const;
     reference front();
     const_reference front() const;
     void pop_back();
     void pop_front();
     void push_back(const T& x);
     void push_front(const T& x);

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
The member function back returns a reference to the last element of the controlled sequence. The member function front returns a reference to the first element of the controlled sequence. The member function pop_back removes the last element of the controlled sequence. The member function pop_front removes the first element of the controlled sequence. All the above functions require that the controlled sequence be non-empty. The member function push_back inserts an element with value x at the end of the controlled sequence. The member function push_front inserts an element with value x at the beginning of the controlled sequence.

Sample Code:

//////////////////////////////////////////////////////////////////////
//
// Compile options needed: -GX
//
// liststck.cpp :  This example shows how to use the various stack
//                 like functions of list.
//
// Functions:
//
//    list::back
//    list::front
//    list::pop_back
//    list::pop_front
//    list::push_back
//    list::push_front
//////////////////////////////////////////////////////////////////////

#include <list>
#include <string>
#include <iostream>

using namespace std ;

typedef list<string> LISTSTR;

void main()
{
    LISTSTR test;

    test.push_back("back");
    test.push_front("middle");
    test.push_front("front");

    // front
    cout << test.front() << endl;

    // back
    cout << test.back() << endl;

    test.pop_front();
    test.pop_back();

    // middle
    cout << test.front() << endl;
}

Program Output is:

front
back
middle


list::insert (STL Sample)

The sample code below illustrates how to use the list::insert STL function in Visual C++.

Required Header:
<list>

Prototype:

     iterator insert(iterator it, const T& x = T());
     void insert(iterator it, size_type n, const T& x);
     void insert(iterator it, const_iterator first, const_iterator last);
     void insert(iterator it, const T *first, const T *last);

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
Each of the member functions inserts, after the element pointed to by it in the controlled sequence, a sequence specified by the remaining operands. The first member function inserts a single element with value x and returns an iterator that points to the newly inserted element. The second member function inserts a repetition of n elements of value x. The last two member functions insert the sequence [first, last).

Sample Code:

//////////////////////////////////////////////////////////////////////
//
// Compile options needed: -GX
//
// insert.cpp :  Shows the various ways to insert elements into a
//               list<T>.
//
// Functions:
//
//    list::insert
//////////////////////////////////////////////////////////////////////

#include <list>
#include <iostream>

using namespace std ;

typedef list<int> LISTINT;

void main()
{
    int rgTest1[] = {5,6,7};
    int rgTest2[] = {10,11,12};

    LISTINT listInt;
    LISTINT listAnother;
    LISTINT::iterator i;

    // Insert one at a time
    listInt.insert (listInt.begin(), 2);
    listInt.insert (listInt.begin(), 1);
    listInt.insert (listInt.end(), 3);

    // 1 2 3
    for (i = listInt.begin(); i != listInt.end(); ++i)
        cout << *i << " ";
    cout << endl;

    // Insert 3 fours
    listInt.insert (listInt.end(), 3, 4);

    // 1 2 3 4 4 4
    for (i = listInt.begin(); i != listInt.end(); ++i)
        cout << *i << " ";
    cout << endl;

    // Insert an array in there
    listInt.insert (listInt.end(), rgTest1, rgTest1 + 3);

    // 1 2 3 4 4 4 5 6 7
    for (i = listInt.begin(); i != listInt.end(); ++i)
        cout << *i << " ";
    cout << endl;

    // Insert another LISTINT
    listAnother.insert (listAnother.begin(), rgTest2, rgTest2+3);
    listInt.insert (listInt.end(), listAnother.begin(), listAnother.end());

    // 1 2 3 4 4 4 5 6 7 10 11 12
    for (i = listInt.begin(); i != listInt.end(); ++i)
        cout << *i << " ";
    cout << endl;
}

Program Output is:

1 2 3
1 2 3 4 4 4
1 2 3 4 4 4 5 6 7
1 2 3 4 4 4 5 6 7 10 11 12


list::list (STL Sample)

The sample code below illustrates how to use the list::list STL function in Visual C++.

Required Header:
<list>

Prototype:

     explicit list(const A& al = A());
     explicit list(size_type n, const T& v = T(), const A& al = A());
     list(const list& x);
     list(const_iterator first, const_iterator last, const A& al = A());

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
The first constructor specifies an empty initial controlled sequence. The second constructor specifies a repetition of n elements of value x. The third constructor specifies a copy of the sequence controlled by x. The last constructor specifies the sequence [first, last). All constructors store the allocator object 'al', or for the copy constructor, the return value of 'x.get_allocator()', in the data member 'allocator' and initialize the controlled sequence.

Sample Code:

//////////////////////////////////////////////////////////////////////
//
// Compile options needed: -GX
//
// list.cpp : demonstrates the different constructors for list<T>
//
// Functions:
//
//    list::list
//////////////////////////////////////////////////////////////////////

#include <list>
#include <string>
#include <iostream>

using namespace std ;

typedef list<string> LISTSTR;

// Try each of the four constructors
void main()
{
    LISTSTR::iterator i;
    LISTSTR test;                   // default constructor

    test.insert(test.end(), "one");
    test.insert(test.end(), "two");

    LISTSTR test2(test);            // construct from another list
    LISTSTR test3(3, "three");      // add several <T>'s
    LISTSTR test4(++test3.begin(),  // add part of another list
             test3.end());

    // Print them all out

    // one two
    for (i =  test.begin(); i != test.end(); ++i)
        cout << *i << " ";
    cout << endl;

    // one two
    for (i =  test2.begin(); i != test2.end(); ++i)
        cout << *i << " ";
    cout << endl;

    // three three three
    for (i =  test3.begin(); i != test3.end(); ++i)
        cout << *i << " ";
    cout << endl;

    // three three
    for (i =  test4.begin(); i != test4.end(); ++i)
        cout << *i << " ";
    cout << endl;
}

Program Output is:

one two
one two
three three three
three three


lower_bound (STL Sample)

The sample code below illustrates how to use the lower_bound STL function in Visual C++.

Required Header:
<algorithm>

Prototype:

template<class ForwardIterator, class T>
     inline ForwardIterator lower_bound(ForwardIterator first, ForwardIterator last, const T& value)

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
The lower_bound algorithm returns the first location in the sequence that value can be inserted such that the order of the sequence is maintained. lower_bound returns an iterator positioned at the location that value can be inserted in the range [first..last), or returns last if no such position exists. lower_bound assumes the range [first..last) is sorted using operator<.

Sample Code:

//////////////////////////////////////////////////////////////////////
//
// Compile options needed: /GX
//
// lower_bound.cpp : Illustrates how to use the lower_bound
//                   function.
//
// Functions:
//
//    lower_bound : Return the lower bound within a range.
//////////////////////////////////////////////////////////////////////

// disable warning C4786: symbol greater than 255 character,
// okay to ignore this warning
#pragma warning(disable: 4786)

#include <iostream>
#include <algorithm>
#include <functional>
#include <vector>

using namespace std;

void main()
{
    const int VECTOR_SIZE = 8 ;

    // Define a template class vector of int
    typedef vector<int > IntVector ;

    //Define an iterator for template class vector of strings
    typedef IntVector::iterator IntVectorIt ;

    IntVector Numbers(VECTOR_SIZE) ;

    IntVectorIt start, end, it, location ;

    // Initialize vector Numbers
    Numbers[0] = 4 ;
    Numbers[1] = 10;
    Numbers[2] = 10 ;
    Numbers[3] = 30 ;
    Numbers[4] = 69 ;
    Numbers[5] = 70 ;
    Numbers[6] = 96 ;
    Numbers[7] = 100;

    start = Numbers.begin() ;   // location of first
                                // element of Numbers

    end = Numbers.end() ;       // one past the location
                                // last element of Numbers

    // print content of Numbers
    cout << "Numbers { " ;
    for(it = start; it != end; it++)
        cout << *it << " " ;
    cout << " }\n" << endl ;

    // return the first location at which 10 can be inserted
    // in Numbers
    location = lower_bound(start, end, 10) ;

    cout << "First location element 10 can be inserted in Numbers is: "
        << location - start << endl ;
}

Program Output is:

Numbers { 4 10 10 30 69 70 96 100  }

First location element 10 can be inserted in Numbers is: 1


Predicate Version of lower_bound (STL Sample)

The sample code below illustrates how to use the the predicate version of the lower_bound STL function in Visual C++.

Required Header:
<algorithm>

Prototype:

template<class ForwardIterator, class T, class Compare>
     inline ForwardIterator lower_bound(ForwardIterator first, ForwardIterator last,
     const T& value, Compare compare)

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
The lower_bound algorithm returns the first location in the sequence that value can be inserted such that the order of the sequence is maintained. lower_bound returns an iterator positioned at the location that value can be inserted in the range [first..last), or returns last if no such position exists. This version assumes the range [first..last) is sorted sequentially using the compare function.

Sample Code:

//////////////////////////////////////////////////////////////////////
//
// Compile options needed: /GX
//
// lower_bound.cpp : Illustrates how to use the lower_bound
//                   function.
//
// Functions:
//
//    lower_bound : Return the lower bound within a range.
//
//////////////////////////////////////////////////////////////////////

// disable warning C4786: symbol greater than 255 character,
// okay to ignore this warning
#pragma warning(disable: 4786)

#include <iostream>
#include <algorithm>
#include <functional>
#include <vector>

using namespace std;

void main()
{
    const int VECTOR_SIZE = 8 ;

    // Define a template class vector of int
    typedef vector<int > IntVector ;

    //Define an iterator for template class vector of strings
    typedef IntVector::iterator IntVectorIt ;

    IntVector Numbers(VECTOR_SIZE) ;

    IntVectorIt start, end, it, location ;

    // Initialize vector Numbers
    Numbers[0] = 4 ;
    Numbers[1] = 10;
    Numbers[2] = 70 ;
    Numbers[3] = 10 ;
    Numbers[4] = 30 ;
    Numbers[5] = 69 ;
    Numbers[6] = 96 ;
    Numbers[7] = 100;

    start = Numbers.begin() ;   // location of first
                                // element of Numbers

    end = Numbers.end() ;       // one past the location
                                // last element of Numbers

    //sort Numbers using the function object less<int>()
    //lower_bound assumes that Numbers is sorted
    //using the "compare" (less<int>() in this case)
    //function
    sort(start, end, less<int>()) ;

    // print content of Numbers
    cout << "Numbers { " ;
    for(it = start; it != end; it++)
        cout << *it << " " ;
    cout << " }\n" << endl ;

    // return the first location at which 10 can be inserted
    // in Numbers
    location = lower_bound(start, end, 10, less<int>()) ;

    cout << "First location element 10 can be inserted in Numbers is: "
        << location - start << endl ;
}

Program Output is:

Numbers { 4 10 10 30 69 70 96 100  }

First location element 10 can be inserted in Numbers is: 1


make_pair (STL Sample)

The sample code below illustrates how to use the make_pair STL function in Visual C++.

Required Header:
<utility>

Prototype:

template<class first, class second> inline
     pair<first, second> make_pair(const first& _X, const second& _Y)

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
The make_pair function creates a pair structure that contains two data elements of any type.

Sample Code:

///////////////////////////////////////////////////////////////////////
// Compile options needed: none
//
// mkpair.cpp: Illustrates how to use the make_pair function.
//
// Functions: make_pair - creates an object pair containing two data
//                        elements of any type.
///////////////////////////////////////////////////////////////////////

/* Compiler options needed: none
*/

#include <utility>
#include <iostream>

using namespace std;

/* STL pair data type containing int and float
*/

typedef struct pair<int,float> PAIR_IF;

void main(void)
{
  PAIR_IF pair1=make_pair(18,3.14f);

  cout << pair1.first << "  " << pair1.second << endl;
  pair1.first=10;
  pair1.second=1.0f;
  cout << pair1.first << "  " << pair1.second << endl;
}

Program Output is:

18  3.14
10  1


map::insert, map::find, and map::end (STL Sample)

The sample code below illustrates how to use the map::insert, map::find, and map::end STL functions in Visual C++.

Required Header:
<map>

Prototype:

iterator map::end();

// Key is the data type of template argument #1 for map
iterator map::find(const Key& key);

pair<iterator, bool> map::insert(const value_type& x);

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
The end() function returns an iterator that points one past the end of a sequence. Find returns an iterator that designates the first element whose sort key equals key. If no such element exists, the iterator equals end(). If the key does not already exist, insert will add it to the sequence and return pair<iterator, true>. If the key already exists, insert does not add it to the sequence and returns pair <iterator, false>. The following sample creates a map of ints to strings. In this case, the mapping is from digits to their string equivalents (1 -> "One", 2 -> "Two", etc.). The program reads a number from the user, finds the word equivalent for each digit (using the map), and prints the number back as a series of words. For example, if the user enters 25463, the program responds with: Two Five Four Six Three.

Sample Code:

//////////////////////////////////////////////////////////////////////
//
// Compile options needed: None
//
// <filename> :  main.cpp
//
// Functions:
//
//      end
//      find
//      insert
//////////////////////////////////////////////////////////////////////

#pragma warning(disable:4786)

#include <iostream>
#include <string>
#include <map>

using namespace std;

typedef map<int, string, less<int> > INT2STRING;

void main()
{
// 1. Create a map of ints to strings
    INT2STRING theMap;
    INT2STRING::iterator theIterator;
    string theString = "";
    int index;

// Fill it with the digits 0 - 9, each mapped to its string counterpart
// Note: value_type is a pair for maps...
    theMap.insert(INT2STRING::value_type(0,"Zero"));
    theMap.insert(INT2STRING::value_type(1,"One"));
    theMap.insert(INT2STRING::value_type(2,"Two"));
    theMap.insert(INT2STRING::value_type(3,"Three"));
    theMap.insert(INT2STRING::value_type(4,"Four"));
    theMap.insert(INT2STRING::value_type(5,"Five"));
    theMap.insert(INT2STRING::value_type(6,"Six"));
    theMap.insert(INT2STRING::value_type(7,"Seven"));
    theMap.insert(INT2STRING::value_type(8,"Eight"));
    theMap.insert(INT2STRING::value_type(9,"Nine"));

// Read a Number from the user and print it back as words
    for( ; ; )
    {
        cout << "Enter \"q\" to quit, or enter a Number: ";
        cin >> theString;
        if(theString == "q")
            break;
        // extract each digit from the string, find its corresponding
        // entry in the map (the word equivalent) and print it
        for(index = 0; index < theString.length(); index++){
            theIterator = theMap.find(theString[index] - '0');
            if(theIterator != theMap.end() )    // is 0 - 9
                cout << (*theIterator).second << " ";
            else    // some character other than 0 - 9
                cout << "[err] ";
        }
        cout << endl;
    }
}

Program Output is:

Enter "q" to quit, or enter a Number: 22
Two Two
Enter "q" to quit, or enter a Number: 33
Three Three
Enter "q" to quit, or enter a Number: 456
Four Five Six
Enter "q" to quit, or enter a Number: q


Non-Predicate Version of max_element (STL Sample)

The sample code below illustrates how to use the non-predicate version of the max_element STL function in Visual C++.

Required Header:
<algorithm>

Prototype:

template<class InputIterator>
     inline InputIterator max_element(InputIterator first, InputIterator last)

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
The max_element algorithm returns the location of the maximum element in the sequence [first, last). The non-predicate version of max_element uses operator< for comparisons.

Sample Code:

//////////////////////////////////////////////////////////////////////
//
// Compile options needed: /GX
//
// max_element.cpp : Illustrates how to use the max_element
//                   function.
//
// Functions:
//
//    max_element : Return the maximum element within a range.
//////////////////////////////////////////////////////////////////////

// disable warning C4786: symbol greater than 255 character,
// okay to ignore
#pragma warning(disable: 4786)

#include <iostream>
#include <algorithm>
#include <functional>
#include <vector>

using namespace std;

void main()
{
    const int VECTOR_SIZE = 8 ;

    // Define a template class vector of int
    typedef vector<int > IntVector ;

    //Define an iterator for template class vector of strings
    typedef IntVector::iterator IntVectorIt ;

    IntVector Numbers(VECTOR_SIZE) ;

    IntVectorIt start, end, it, location ;

    // Initialize vector Numbers
    Numbers[0] = 4 ;
    Numbers[1] = 10;
    Numbers[2] = 10 ;
    Numbers[3] = 30 ;
    Numbers[4] = 69 ;
    Numbers[5] = 70 ;
    Numbers[6] = 96 ;
    Numbers[7] = 100;

    start = Numbers.begin() ;   // location of first
                                // element of Numbers

    end = Numbers.end() ;       // one past the location
                                // last element of Numbers

    // print content of Numbers
    cout << "Numbers { " ;
    for(it = start; it != end; it++)
        cout << *it << " " ;
    cout << " }\n" << endl ;

    // return the maximum element in the Numbers
    location = max_element(start, end) ;

    cout << "The maximum element in Numbers is: "
        << *location << endl ;
}

Program Output is:

Numbers { 4 10 10 30 69 70 96 100  }

The maximum element in Numbers is: 100


Predicate Version of max_element (STL Sample)

The sample code below illustrates how to use the predicate version of the max_element STL function in Visual C++.

Required Header:
<algorithm>

Prototype:

template<class InputIterator, class Compare> inline
     InputIterator max_element(InputIterator first, InputIterator last, Compare compare)

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
The max_element algorithm returns the location of the maximum element in the sequence [first, last). The predicate version of max_element uses the compare function for comparisons.

Sample Code:

//////////////////////////////////////////////////////////////////////
//
// Compile options needed: /GX
//
// max_element.cpp : Illustrates how to use the predicates version
//                   of the max_element function.
//
// Functions:
//
//    max_element : Return the maximum element within a range.
//////////////////////////////////////////////////////////////////////

// disable warning C4786: symbol greater than 255 character,
// okay to ignore
#pragma warning(disable: 4786)

#include <iostream>
#include <algorithm>
#include <functional>
#include <vector>

using namespace std;

void main()
{
    const int VECTOR_SIZE = 8 ;

    // Define a template class vector of int
    typedef vector<int > IntVector ;

    //Define an iterator for template class vector of strings
    typedef IntVector::iterator IntVectorIt ;

    IntVector Numbers(VECTOR_SIZE) ;

    IntVectorIt start, end, it, location ;

    // Initialize vector Numbers
    Numbers[0] = 4 ;
    Numbers[1] = 10;
    Numbers[2] = 10 ;
    Numbers[3] = 30 ;
    Numbers[4] = 69 ;
    Numbers[5] = 70 ;
    Numbers[6] = 96 ;
    Numbers[7] = 100;

    start = Numbers.begin() ;   // location of first
                                // element of Numbers

    end = Numbers.end() ;       // one past the location
                                // last element of Numbers

    // print content of Numbers
    cout << "Numbers { " ;
    for(it = start; it != end; it++)
        cout << *it << " " ;
    cout << " }\n" << endl ;

    // return the maximum element in the Numbers
    location = max_element(start, end, less<int>()) ;

    cout << "The maximum element in Numbers is: "
        << *location << endl ;
}

Program Output is:

Numbers { 4 10 10 30 69 70 96 100  }

The maximum element in Numbers is: 100


map::max_size, clear, erase, size (STL Sample)

The sample code below illustrates how to use the map::max_size, clear, erase, and size STL functions in Visual C++.

Required Header:
<map>

Prototype:

     size_type max_size() const;
     void clear() const;
     bool empty() const;
     iterator erase(iterator first, iterator last);
     size_type size() const;
     A::reference operator[](const Key& key);    // A is the allocator
     iterator map::begin();
     iterator map::end();
     iterator map::find(const Key& key);

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
The following sample creates a map of strings to ints and fills it first with a map of month names to month numbers, then empties and refills it with a map of weekday names to corresponding ints.

Sample Code:

//////////////////////////////////////////////////////////////////////
//
// Compile options needed: None
//
// <filename> :  main.cpp
//
// Functions:    iterator map::max_size();
//               void clear() const;
//               bool empty() const;
//               iterator erase(iterator first, iterator last);
//               size_type size() const;
//               A::reference operator[](const Key& key);
//               iterator map::begin();
//               iterator map::end();
//               iterator map::find(const Key& key);
//////////////////////////////////////////////////////////////////////

#pragma warning(disable:4786)

#include <iostream>
#include <string>
#include <map>

using namespace std ;

typedef map<string, int> STRING2INT;

void main()
{
    STRING2INT MyMap;
    STRING2INT::iterator MyIterator;
    string MyBuffer;

    // print the maximum number of <key,data> pairs that MyMap can hold
    cout << "MyMap is capable of holding " << MyMap.max_size()
         << " <string,int> pairs" << endl;

    if(!MyMap.empty())
        cout << "MyMap has " << MyMap.size() << " entries" << endl;
    else
        cout << "MyMap is empty" << endl;
        cout << "Entering new entries in MyMap" << endl;
    // Fill in MyMap with the months of the year, mapped to their number
    // January - 1, February - 2, etc. using operator[].
    MyMap["January"] = 1;
    MyMap["February"] = 2;
    MyMap["March"] = 3;
    MyMap["April"] = 4;
    MyMap["May"] = 5;
    MyMap["June"] = 6;
    MyMap["July"] = 7;
    MyMap["August"] = 8;
    MyMap["September"] = 9;
    MyMap["October"] = 10;
    MyMap["November"] = 11;
    MyMap["December"] = 12;

    if(!MyMap.empty())
        cout << "MyMap has " << MyMap.size() << " entries" << endl;
    else
        cout << "MyMap is empty" << endl;

    // Ask the user for a month of the year and print the number
    // that corresponds to the month entered
    //MyIterator = MyMap.end();
    while(MyIterator == MyMap.end()){
        cout << "Enter a Month :";
        cin >> MyBuffer;
        if((MyIterator = MyMap.find(MyBuffer)) != MyMap.end())
            cout << (*MyIterator).first << " is Month Number "
                 << (*MyIterator).second << endl;
        else
            cout << "Enter a Valid Month (example: March)" << endl;
    }

    // empty MyMap - note that clear simply calls erase(begin(),end());
    MyMap.clear();

    if(!MyMap.empty())
        cout << "MyMap has " << MyMap.size() << " entries" << endl;
    else
        cout << "MyMap is empty" << endl;
        cout << "Entering new entries in MyMap" << endl;
    // Fill MyMap with the days of the week, each mapped to an int
    MyMap["Monday"] = 1;
    MyMap["Tuesday"] = 2;
    MyMap["Wednesday"] = 3;
    MyMap["Thursday"] = 4;
    MyMap["Friday"] = 5;
    MyMap["Saturday"] = 6;
    MyMap["Sunday"] = 7;

    if(!MyMap.empty())
        cout << "MyMap has " << MyMap.size() << " entries" << endl;
    else
        cout << "MyMap is empty" << endl;

    // Ask the user for a day of the week and print the number
    // that corresponds to the day entered
    MyIterator = MyMap.end();
    while(MyIterator == MyMap.end()){
        cout << "Enter a Day of the Week:";
        cin >> MyBuffer;
        if((MyIterator = MyMap.find(MyBuffer)) != MyMap.end())
            cout << (*MyIterator).first << " is Day Number "
                 << (*MyIterator).second << endl;
        else
            cout <<"Enter a Valid Day of the Week(example: Monday)"<< endl;
    }
// Now clear MyMap again - this time using erase instead of clear
    MyMap.erase(MyMap.begin(), MyMap.end());

    if(!MyMap.empty())
        cout << "MyMap has " << MyMap.size() << " entries" << endl;
    else
        cout << "MyMap is empty" << endl;

}

Program Output is:

MyMap is capable of holding 1073741823 <string,int> pairs
MyMap is empty
Entering new entries in MyMap
MyMap has 12 entries
Enter a Month :[April]
April is Month Number 4
MyMap is empty
Entering new entries in MyMap
MyMap has 7 entries
Enter a Day of the Week:[Friday]
Enter a Valid Day of the Week(example: Monday)
Enter a Day of the Week:[Friday]
Friday is Day Number 5
MyMap is empty


merge (STL Sample)

The sample code below illustrates how to use the merge STL function in Visual C++.

Required Header:
<algorithm>

Prototype:

template<class InputIterator1,
     class InputIterator2,
     class OutputIterator> inline
     OutputIterator merge( InputIterator1 first1,
     InputIterator1 last1,
     InputIterator2 first2,
     InputIterator2 last2
     OutputIterator result )

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
The merge algorithm merges two sorted sequences: [first1..last1) and [first2..last2) into a single sorted sequence starting at result. This version assumes that the ranges [first1..last1) and [first2..last2) are sorted using operator<. If both ranges contain equal values, the value from the first range will be stored first. The result of merging overlapping ranges is undefined.

Sample Code:

//////////////////////////////////////////////////////////////////////
//
// Compile options needed: /GX
//
// merge.cpp : Illustrates how to use the merge
//                     function.
//
// Functions:
//
//    merge : Merge two sorted sequences
//            into a single sorted list.
//////////////////////////////////////////////////////////////////////

// disable warning C4786: symbol greater than 255 character,
// okay to ignore
#pragma warning(disable: 4786)

#include <iostream>
#include <algorithm>
#include <vector>
#include <list>
#include <deque>

using namespace std ;

void main()
{
    const int MAX_ELEMENTS = 8 ;

    // Define a template class vector of int
    typedef vector<int> IntVector ;

    //Define an iterator for template class vector of ints
    typedef IntVector::iterator IntVectorIt ;

    IntVector NumbersVector(MAX_ELEMENTS) ;

    IntVectorIt startv, endv, itv ;

    // Define a template class list of int
    typedef list<int> IntList ;

    //Define an iterator for template class list of ints
    typedef IntList::iterator IntListIt ;

    IntList NumbersList ;

    IntListIt first, last, itl ;

    // Define a template class deque of int
    typedef deque<int> IntDeque ;

    //Define an iterator for template class deque of ints
    typedef IntDeque::iterator IntDequeIt ;

    IntDeque NumbersDeque(2 * MAX_ELEMENTS) ;

    IntDequeIt itd ;

    // Initialize vector NumbersVector
    NumbersVector[0] = 4 ;
    NumbersVector[1] = 10;
    NumbersVector[2] = 70 ;
    NumbersVector[3] = 10 ;
    NumbersVector[4] = 30 ;
    NumbersVector[5] = 69 ;
    NumbersVector[6] = 96 ;
    NumbersVector[7] = 100;

    startv = NumbersVector.begin() ;   // location of first
                                       // element of NumbersVector

    endv = NumbersVector.end() ;  // one past the location
                                  // last element of NumbersVector

    // sort NumbersVector, merge requires the sequences
    // to be sorted
    sort(startv, endv) ;

    // print content of NumbersVector
    cout << "NumbersVector { " ;
    for(itv = startv; itv != endv; itv++)
        cout << *itv << " " ;
    cout << " }\n" << endl ;

    // Initialize vector NumbersList
    for(int i = 0; i < MAX_ELEMENTS; i++)
        NumbersList.push_back(i) ;

    first = NumbersList.begin() ;   // location of first
                                     // element of NumbersList

    last = NumbersList.end() ;  // one past the location
                                // last element of NumbersList

    // print content of NumbersList
    cout << "NumbersList { " ;
    for(itl = first; itl != last; itl++)
        cout << *itl << " " ;
    cout << " }\n" << endl ;

    // merge the elements of NumbersVector
    // and NumbersList and place the
    // results in NumbersDeque
    merge(startv, endv, first, last, NumbersDeque.begin()) ;

    cout << "After calling merge\n" << endl ;

    // print content of NumbersDeque
    cout << "NumbersDeque { " ;
    for(itd = NumbersDeque.begin();
        itd != NumbersDeque.end(); itd++)
        cout << *itd << " " ;
    cout << " }\n" << endl ;
}

Program Output is:

NumbersVector { 4 10 10 30 69 70 96 100  }

NumbersList { 0 1 2 3 4 5 6 7  }

After calling merge

NumbersDeque { 0 1 2 3 4 4 5 6 7 10 10 30 69 70 96 100  }


Predicate Version of merge (STL Sample)

The sample code below illustrates how to use the predicate version of the merge STL function in Visual C++.

Required Header:
<algorithm>

Prototype:

template<class InputIterator1,
     class InputIterator2,
     class OutputIterator
     class Compare> inline
     OutputIterator merge( InputIterator1 first1,
     InputIterator1 last1,
     InputIterator2 first2,
     InputIterator2 last2
     OutputIterator result,
     Compare compare )

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
The merge algorithm merges two sorted sequences: [first1..last1) and [first2..last2) into a single sorted sequence starting at result. This version assumes that the ranges [first1..last1) and [first2..last2) are sorted using the compare function. If both ranges contain equal values, the value from the first range will be stored first. The result of merging overlapping ranges is undefined.

Sample Code:

//////////////////////////////////////////////////////////////////////
//
// Compile options needed: /GX
//
// merge.cpp : Illustrates how to use predicate version of the merge
//             function.
//
// Functions:
//
//    merge : Merge two sorted sequences
//            into a single sorted list.
//////////////////////////////////////////////////////////////////////

// disable warning C4786: symbol greater than 255 character,
// okay to ignore
#pragma warning(disable: 4786)

#include <iostream>
#include <algorithm>
#include <vector>
#include <list>
#include <deque>

using namespace std ;

void main()
{
    const int MAX_ELEMENTS = 8 ;

    // Define a template class vector of int
    typedef vector<int> IntVector ;

    //Define an iterator for template class vector of ints
    typedef IntVector::iterator IntVectorIt ;

    IntVector NumbersVector(MAX_ELEMENTS) ;

    IntVectorIt startv, endv, itv ;

    // Define a template class list of int
    typedef list<int> IntList ;

    //Define an iterator for template class list of ints
    typedef IntList::iterator IntListIt ;

    IntList NumbersList ;

    IntListIt first, last, itl ;

    // Define a template class deque of int
    typedef deque<int> IntDeque ;

    //Define an iterator for template class deque of ints
    typedef IntDeque::iterator IntDequeIt ;

    IntDeque NumbersDeque(2 * MAX_ELEMENTS) ;

    IntDequeIt itd ;

    // Initialize vector NumbersVector
    NumbersVector[0] = 4 ;
    NumbersVector[1] = 10;
    NumbersVector[2] = 70 ;
    NumbersVector[3] = 10 ;
    NumbersVector[4] = 30 ;
    NumbersVector[5] = 69 ;
    NumbersVector[6] = 96 ;
    NumbersVector[7] = 100;

    startv = NumbersVector.begin() ;   // location of first
                                       // element of NumbersVector

    endv = NumbersVector.end() ;  // one past the location
                                  // last element of NumbersVector

    // sort NumbersVector, merge requires the sequences
    // to be sorted
    sort(startv, endv, less<int>()) ;

    // print content of NumbersVector
    cout << "NumbersVector { " ;
    for(itv = startv; itv != endv; itv++)
        cout << *itv << " " ;
    cout << " }\n" << endl ;

    // Initialize vector NumbersList
    for(int i = 0; i < MAX_ELEMENTS; i++)
        NumbersList.push_back(i) ;

    first = NumbersList.begin() ;   // location of first
                                     // element of NumbersList

    last = NumbersList.end() ;  // one past the location
                                // last element of NumbersList

    // print content of NumbersList
    cout << "NumbersList { " ;
    for(itl = first; itl != last; itl++)
        cout << *itl << " " ;
    cout << " }\n" << endl ;

    // merge the elements of NumbersVector
    // and NumbersList and place the
    // results in NumbersDeque
    merge(startv, endv, first, last, NumbersDeque.begin(), less<int>()) ;

    cout << "After calling merge\n" << endl ;

    // print content of NumbersDeque
    cout << "NumbersDeque { " ;
    for(itd = NumbersDeque.begin();
        itd != NumbersDeque.end(); itd++)
        cout << *itd << " " ;
    cout << " }\n" << endl ;
}

Program Output is:

NumbersVector { 4 10 10 30 69 70 96 100  }

NumbersList { 0 1 2 3 4 5 6 7  }

After calling merge

NumbersDeque { 0 1 2 3 4 4 5 6 7 10 10 30 69 70 96 100  }


min_element (STL Sample)

The sample code below illustrates how to use the min_element STL function in Visual C++.

Required Header:
<algorithm>

Prototype:

template<class InputIterator> inline
     InputIterator min_element(InputIterator first, InputIterator last)

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
The min_element algorithm returns the location of the minimum element in the sequence [first, last). The non-predicate version of min_element uses operator< for comparisons.

Sample Code:

//////////////////////////////////////////////////////////////////////
//
// Compile options needed: /GX
//
// min_element.cpp : Illustrates how to use the min_element
//                   function.
//
// Functions:
//
//    min_element - Return the minimum element within a range.
//////////////////////////////////////////////////////////////////////

// disable warning C4786: symbol greater than 255 character,
// okay to ignore
#pragma warning(disable: 4786)

#include <iostream>
#include <algorithm>
#include <functional>
#include <vector>

using namespace std;

void main()
{
    const int VECTOR_SIZE = 8 ;

    // Define a template class vector of int
    typedef vector<int > IntVector ;

    //Define an iterator for template class vector of strings
    typedef IntVector::iterator IntVectorIt ;

    IntVector Numbers(VECTOR_SIZE) ;

    IntVectorIt start, end, it, location ;

    // Initialize vector Numbers
    Numbers[0] = 4 ;
    Numbers[1] = 10 ;
    Numbers[2] = 10 ;
    Numbers[3] = 30 ;
    Numbers[4] = 69 ;
    Numbers[5] = 70 ;
    Numbers[6] = 96 ;
    Numbers[7] = 100 ;

    start = Numbers.begin() ;   // location of first
                                // element of Numbers

    end = Numbers.end() ;       // one past the location
                                // last element of Numbers

    // print content of Numbers
    cout << "Numbers { " ;
    for(it = start; it != end; it++)
        cout << *it << " " ;
    cout << " }\n" << endl ;

    // return the minimum element in the Numbers
    location = min_element(start, end) ;

    cout << "The minimum element in Numbers is: "
        << *location << endl ;
}

Program Output is:

Numbers { 4 10 10 30 69 70 96 100  }

The minimum element in Numbers is: 4


Predicate Version of min_element (STL Sample)

The sample code below illustrates how to use the predicate version of the min_element STL function in Visual C++.

Required Header:
<algorithm>

Prototype:

template<class InputIterator, class Compare> inline
     InputIterator min_element(InputIterator first, InputIterator last, Compare compare)

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
The min_element algorithm returns the location of the minimum element in the sequence [first, last). The predicate version of min_element uses the compare function for comparisons.

Sample Code:

//////////////////////////////////////////////////////////////////////
//
// Compile options needed: /GX
//
// min_element.cpp : Illustrates how to use the predicates version
//                   of the min_element function.
//
// Functions:
//
//    min_element : Return the minimum element within a range.
//////////////////////////////////////////////////////////////////////

// disable warning C4786: symbol greater than 255 character,
// okay to ignore
#pragma warning(disable: 4786)

#include <iostream>
#include <algorithm>
#include <functional>
#include <vector>

using namespace std;

void main()
{
    const int VECTOR_SIZE = 8 ;

    // Define a template class vector of int
    typedef vector<int > IntVector ;

    //Define an iterator for template class vector of strings
    typedef IntVector::iterator IntVectorIt ;

    IntVector Numbers(VECTOR_SIZE) ;

    IntVectorIt start, end, it, location ;

    // Initialize vector Numbers
    Numbers[0] = 4 ;
    Numbers[1] = 10;
    Numbers[2] = 10 ;
    Numbers[3] = 30 ;
    Numbers[4] = 69 ;
    Numbers[5] = 70 ;
    Numbers[6] = 96 ;
    Numbers[7] = 100;

    start = Numbers.begin() ;   // location of first
                                // element of Numbers

    end = Numbers.end() ;       // one past the location
                                // last element of Numbers

    // print content of Numbers
    cout << "Numbers { " ;
    for(it = start; it != end; it++)
        cout << *it << " " ;
    cout << " }\n" << endl ;

    // return the minimum element in the Numbers
    location = min_element(start, end, less<int>()) ;

    cout << "The minimum element in Numbers is: "
        << *location << endl ;
}

Program Output is:

Numbers { 4 10 10 30 69 70 96 100  }

The minimum element in Numbers is: 4


new operator (STL Sample)

The sample code below illustrates how to use the new operator.

Required Header:
<new>

Prototype:

   void *operator new(size_t n)
   void *operator new(size_t n, const nothrow&)
   void *operator new[](size_t n);

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
The first operator new will attempt to allocate memory and if it fails, will throw an exception. The second operator new accepts a second parameter of type nothrow. This parameter indicates that if the allocation fails, it should return NULL and not throw an exception. The third operator new will allocate memory for an array of that type and if it fails, will throw an exception.

Sample Code:

//////////////////////////////////////////////////////////////////////
//
// Compile options needed: /GX
//
// <filename> :  newop.cpp
//
// Functions:
//
//    void *operator new(size_t n)
//
//    void *operator new(size_t n, const nothrow&)
//
//    void *operator new[](size_t n);
//////////////////////////////////////////////////////////////////////

/* Compile options needed: /GX
*/

#include <new>
#include <iostream>

using namespace std;

class BigClass {
public:
    BigClass() {};
    ~BigClass(){}
        double BigArray[99999999];
};

void main()
{
    try {
    BigClass * p = new BigClass;
    }
    catch( bad_alloc a) {
        const char * temp = a.what();
        cout << temp << endl;
        cout << "Threw a bad_alloc exception" << endl;
    }
    BigClass * q = new(nothrow) BigClass;
    if ( q == NULL )
        cout << "Returned a NULL pointer" << endl;

    try {
    BigClass * r = new BigClass[3];
    }
    catch( bad_alloc a) {
        const char * temp = a.what();
        cout << temp << endl;
        cout << "Threw a bad_alloc exception" << endl;
    }
}

Program Output is:

bad allocation
Threw a bad_alloc exception
Returned a NULL pointer
bad allocation
Threw a bad_alloc exception


next_permutation (STL Sample)

The sample code below illustrates how to use the next_permutation STL function in Visual C++.

Required Header:
<algorithm>

Prototype:

template<class BidirectionalIterator> inline
     bool next_permutation(BidirectionalIterator first,
     BidirectionalIterator last)

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
The next_permutation algorithm changes the order of the elements in the range [first, last) to the next lexicographic permutation and returns true. If there is no next_permutation, it arranges the sequence to be the first permutation and returns false. IMPORTANT: The next_permutation algorithm assumes the sequence is sorted in ascending order using operator<. The non-predicate version uses the operator< to order the permutations.

Sample Code:

//////////////////////////////////////////////////////////////////////
//
// Compile options needed: /GX
//
// next_permutation.cpp : Illustrates how to use the
//                        next_permutation function.
//
// Functions:
//
//    next_permutation : Change the order of the sequence to the
//                       next lexicograhic permutation.
//////////////////////////////////////////////////////////////////////

// disable warning C4786: symbol greater than 255 character,
// okay to ignore
#pragma warning(disable: 4786)

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <functional>

using namespace std ;

void main()
{
    const int VECTOR_SIZE = 3 ;

    // Define a template class vector of strings
    typedef vector<string> StrVector ;

    //Define an iterator for template class vector of strings
    typedef StrVector::iterator StrVectorIt ;

    //Define an ostream iterator for strings
    typedef ostream_iterator<string> StrOstreamIt;

    StrVector Pattern(VECTOR_SIZE) ;

    StrVectorIt start, end, it ;

    StrOstreamIt outIt(cout, " ") ;

    start = Pattern.begin() ;   // location of first
                                      // element of Pattern

    end = Pattern.end() ;       // one past the location last
                                       // element of Pattern

    //Initialize vector Pattern
    Pattern[0] = "A" ;
    Pattern[1] = "B" ;
    Pattern[2] = "C" ;

    // print content of Pattern
    cout << "Before calling next_permutation...\n" << "Pattern: " ;
    for(it = start; it != end; it++)
        cout << *it << " " ;
    cout << "\n\n" ;

    // Generate all possible permutations

    cout << "After calling next_permutation...." << endl ;
    while ( next_permutation(start, end) )
    {
        copy(start, end, outIt) ;
        cout << endl ;
    }
}

Program Output is:

Before calling next_permutation:
Pattern: A B C

After calling next_permutation:
A C B
B A C
B C A
C A B
C B A


Predicate Version of next_permutation (STL Sample)

The sample code below illustrates how to use the predicate version of the next_permutation STL function in Visual C++.

Required Header:
<algorithm>

Prototype:

template<class BidirectionalIterator, class Compare> inline
     bool next_permutation(BidirectionalIterator first,
     BidirectionalIterator last,
     Compare compare)

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
The next_permutation algorithm changes the order of the elements in the range [first, last) to the next lexicographic permutation and returns true. If there is no next_permutation, it arranges the sequence to be the first permutation and returns false. NOTE: The next_permutation algorithm assumes that the sequence is sorted in ascending order using the compare function. The non-predicate version uses the compare function to order the permutations.

Sample Code:

//////////////////////////////////////////////////////////////////////
//
// Compile options needed: /GX
//
// next_permutation.cpp : Illustrates how to use the predicate version
//                        of the next_permutation function.
//
// Functions:
//
//    next_permutation : Change the order of the sequence to the
//                       next lexicograhic permutation.
//////////////////////////////////////////////////////////////////////

// disable warning C4786: symbol greater than 255 character,
// okay to ignore
#pragma warning(disable: 4786)

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <functional>

using namespace std ;

void main()
{
    const int VECTOR_SIZE = 3 ;

    // Define a template class vector of strings
    typedef vector<string> StrVector ;

    //Define an iterator for template class vector of strings
    typedef StrVector::iterator StrVectorIt ;

    //Define an ostream iterator for strings
    typedef ostream_iterator<string> StrOstreamIt;

    StrVector Pattern(VECTOR_SIZE) ;

    StrVectorIt start, end, it ;

    StrOstreamIt outIt(cout, " ") ;

    start = Pattern.begin() ;   // location of first
                                      // element of Pattern

    end = Pattern.end() ;       // one past the location last
                                       // element of Pattern

    //Initialize vector Pattern
    Pattern[0] = "K" ;
    Pattern[1] = "A" ;
    Pattern[2] = "L" ;

    //sort the contents of Pattern, required by next_permutation
    sort(start, end, less<string>()) ;

    // print content of Pattern
    cout << "Before calling next_permutation...\n" << "Pattern: " ;
    for(it = start; it != end; it++)
        cout << *it << " " ;
    cout << "\n\n" ;

    // Generate all possible permutations

    cout << "After calling next_permutation...." << endl ;
    while ( next_permutation(start, end, less<string>()) )
    {
        copy(start, end, outIt) ;
        cout << endl ;
    }
}

Program Output is:

Before calling next_permutation:
Pattern: A K L

After calling next_permutation:.
A L K
K A L
K L A
L A K
L K A


nth_element (STL Sample)

The sample code below illustrates how to use the nth_element STL function in Visual C++.

Required Header:
<algorithm>

Prototype:

template<class RandomAccessIterator> inline
     void nth_element(RandomAccessIterator first,
     RandomAccessIterator nth,
     RandomAccessIterator last)

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
The nth_element algorithm partitions the sequence [first..last) on the value referenced by nth. All the elements less than or equal to the value are placed before value and all elements greater than value are placed after value in the sequence. The non-predicate version of nth_element uses operator< for comparisons.

Sample Code:

//////////////////////////////////////////////////////////////////////
//
// Compile options needed: /GX
//
// nth_element.cpp : Illustrates how to use the nth_element
//                   function.
//
// Functions:
//
//   nth_element : Partition the elements in a sequence by its nth
//                 element.
//////////////////////////////////////////////////////////////////////

// disable warning C4786: symbol greater than 255 character,
// okay to ignore
#pragma warning(disable: 4786)

#include <iostream>
#include <algorithm>
#include <functional>
#include <vector>

using namespace std ;

void main()
{
    const int VECTOR_SIZE = 8 ;

    // Define a template class vector of int
    typedef vector<int> IntVector ;

    //Define an iterator for template class vector of strings
    typedef IntVector::iterator IntVectorIt ;

    IntVector Numbers(VECTOR_SIZE) ;

    IntVectorIt start, end, it ;

    // Initialize vector Numbers
    Numbers[0] = 4 ;
    Numbers[1] = 10;
    Numbers[2] = 70 ;
    Numbers[3] = 30 ;
    Numbers[4] = 10;
    Numbers[5] = 69 ;
    Numbers[6] = 96 ;
    Numbers[7] = 100;

    start = Numbers.begin() ;   // location of first
                                // element of Numbers

    end = Numbers.end() ;       // one past the location
                                // last element of Numbers

    cout << "Before calling nth_element\n" << endl ;

    // print content of Numbers
    cout << "Numbers { " ;
    for(it = start; it != end; it++)
        cout << *it << " " ;
    cout << " }\n" << endl ;

    // partition the elements by the 4th element
    nth_element(start, start+4, end) ;

    cout << "After calling nth_element\n" << endl ;

    cout << "Numbers { " ;
    for(it = start; it != end; it++)
        cout << *it << " " ;
    cout << " }\n" << endl ;
}

Program Output is:

Before calling nth_element

Numbers { 4 10 70 30 10 69 96 100  }

After calling nth_element

Numbers { 4 10 10 30 69 70 96 100  }


Predicate Version of nth_element (STL Sample)

The sample code below illustrates how to use the predicate version of the nth_element STL function in Visual C++.

Required Header:
<algorithm>

Prototype:

template<class RandomAccessIterator, class Compare>
     inline void nth_element(RandomAccessIterator first, RandomAccessIterator nth,
     RandomAccessIterator last, Compare compare)

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
The nth_element algorithm partitions the sequence [first..last) on the value referenced by nth. All the elements less than or equal to the value are placed before value and all elements greater than value are placed after value in the sequence. The predicate version of nth_element uses the compare function for comparisons.

Sample Code:

//////////////////////////////////////////////////////////////////////
//
// Compile options needed: /GX
//
// nth_element.cpp : Illustrates how to use the predicate version
//                   of the nth_element function.
//
// Functions:
//
//    nth_element : Partition the elements in a sequence by its nth
//                  element.
//////////////////////////////////////////////////////////////////////

// disable warning C4786: symbol greater than 255 character,
// okay to ignore
#pragma warning(disable: 4786)

#include <iostream>
#include <algorithm>
#include <functional>
#include <vector>

using namespace std;

void main()
{
    const int VECTOR_SIZE = 8 ;

    // Define a template class vector of int
    typedef vector<int > IntVector ;

    //Define an iterator for template class vector of strings
    typedef IntVector::iterator IntVectorIt ;

    IntVector Numbers(VECTOR_SIZE) ;

    IntVectorIt start, end, it ;

    // Initialize vector Numbers
    Numbers[0] = 4 ;
    Numbers[1] = 10;
    Numbers[2] = 70 ;
    Numbers[3] = 30 ;
    Numbers[4] = 10;
    Numbers[5] = 69 ;
    Numbers[6] = 96 ;
    Numbers[7] = 100;

    start = Numbers.begin() ;   // location of first
                                // element of Numbers

    end = Numbers.end() ;       // one past the location
                                // last element of Numbers

    cout << "Before calling nth_element:\n" << endl ;

    // print content of Numbers
    cout << "Numbers { " ;
    for(it = start; it != end; it++)
        cout << *it << " " ;
    cout << " }\n" << endl ;

    // partition the elements by the 4th element
    nth_element(start, start+4, end, less<int>()) ;

    cout << "After calling nth_element:\n" << endl ;

    cout << "Numbers { " ;
    for(it = start; it != end; it++)
        cout << *it << " " ;
    cout << " }\n" << endl ;
}

Program Output is:

Before calling nth_element:

Numbers { 4 10 70 30 10 69 96 100  }

After calling nth_element:

Numbers { 4 10 10 30 69 70 96 100  }


Members of the numeric_limits Class (STL Sample)

The sample code below illustrates how to use the members of the numeric_limits class in Visual C++.

Required Header:
<limits>

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
To reference one of the members of this class, you need to specify the type that you want to obtain information about and the member name. The return will either be a value of 1 for true or 0 for false. For example, numeric_limits<int>::min() will return the minimum value for an int. NOTE: Some of the members are valid only for certain types. Please refer to the Online Help to determine if a member is valid only for a certain type.

Sample Code:

//////////////////////////////////////////////////////////////////////
//
// Compile options needed: /GX
//
// <filename> :  Numeric.cpp
//
// Variables and Functions:
//
//    has_denorm
//    has_denorm_loss
//    has_infinity
//    has_quiet_NaN
//    has_signaling_NaN
//    is_bounded
//    is_exact
//    is_iec559
//    is_integer
//    is_modulo
//    is_signed
//    is_specialized
//    tinyness_before
//    traps
//    round_style
//    digits
//    digits10
//    max_exponent
//    max_exponent10
//    min_exponent
//    min_exponent10
//    radix;
//    denorm_min()
//    epsilon()
//    infinity()
//    max()
//    min()
//    quiet_ NaN()
//    round_error()
//    signaling_NaN()
//////////////////////////////////////////////////////////////////////

/* Compile options needed: /GX
*/

#include <iostream>
#include <limits>

using namespace std;

void main() {
    cout << " 1 The minimum value for char is " <<
        (int)numeric_limits<char>::min() << endl;
    cout << " 2 The minimum value for int is " <<
        numeric_limits<int>::min() << endl;
    cout << " 3 The maximum value for char is " <<
        (int)numeric_limits<char>::max() << endl;
    cout << " 4 The maximum value for int is " <<
        numeric_limits<int>::max() << endl;
    cout << " 5 The number of bits to represent a char is " <<
        numeric_limits<char>::digits << endl;
    cout << " 6 The number of bits to represent an int is " <<
        numeric_limits<int>::digits << endl;
    cout <<" 7 The number of digits representable in base 10 for float is"
         << numeric_limits<float>::digits10 << endl;
    cout << " 8 Is a char signed?              " <<
        numeric_limits<char>::is_signed << endl;
    cout << " 9 Is an unsigned integer signed? " <<
        numeric_limits<unsigned int>::is_signed << endl;
    cout << "10 Is a integer an integer? " <<
        numeric_limits<int>::is_integer << endl;
    cout << "11 Is a float an integer?   " <<
        numeric_limits<float>::is_integer << endl;
    cout << "12 Is a integer exact? " <<
        numeric_limits<int>::is_exact << endl;
    cout << "13 Is a float  exact?  " <<
        numeric_limits<float>::is_exact << endl;
    cout << "14 The radix for float is            "  <<
        numeric_limits<float>::radix << endl;
    cout << "15 The epsilon for float is          " <<
        numeric_limits<float>::epsilon() << endl;
    cout << "16 The round error for float is      " <<
        numeric_limits<float>::round_error() << endl;
    cout << "17 The minimum exponent for float is " <<
        numeric_limits<float>::min_exponent << endl;
    cout << "18 The minimum exponent in base 10   " <<
        numeric_limits<float>::min_exponent10 << endl;
    cout << "19 The maximum exponent is           " <<
        numeric_limits<float>::max_exponent << endl;
    cout << "20 The maximum exponent in base 10   " <<
        numeric_limits<float>::max_exponent10 << endl;
    cout << "21 Can float represent positive infinity?  " <<
        numeric_limits<float>::has_infinity << endl;
    cout << "22 Can double represent positive infinity? " <<
        numeric_limits<double>::has_infinity << endl;
    cout << "23 Can int represent positive infinity? " <<
        numeric_limits<int>::has_infinity << endl;
    cout << "24 Can float represent a NaN?           " <<
        numeric_limits<float>::has_quiet_NaN << endl;
    cout << "25 Can float represent a signaling NaN? " <<
        numeric_limits<float>::has_signaling_NaN << endl;
    cout << "26 Does float allow denormalized values?   " <<
        numeric_limits<float>::has_denorm << endl;
    cout << "27 Does float detect denormalization loss? " <<
        numeric_limits<float>::has_denorm_loss << endl;
    cout << "28 Representation of positive infinity for float " <<
        numeric_limits<float>::infinity() << endl;
    cout << "29 Representation of quiet NaN for float         " <<
        numeric_limits<float>::quiet_NaN() << endl;
    cout << "30 Minimum denormalized number for float         " <<
        numeric_limits<float>::denorm_min() << endl;
    cout << "31 Minimum positive denormalized value for float " <<
        numeric_limits<float>::denorm_min() << endl;
    cout << "32 Does float adhere to IEC 559 standard?  " <<
        numeric_limits<float>::is_iec559 << endl;
    cout << "33 Is float bounded? " <<
        numeric_limits<float>::is_bounded << endl;
    cout << "34 Is float modulo?  " <<
        numeric_limits<float>::is_modulo << endl;
    cout << "35 Is int modulo?    " <<
        numeric_limits<float>::is_modulo << endl;
    cout << "36 Is trapping implemented for float?    " <<
        numeric_limits<float>::traps << endl;
    cout << "37 Is tinyness detected before rounding? " <<
        numeric_limits<float>::tinyness_before << endl;
    cout << "38 What is the rounding style for float? " <<
        (int)numeric_limits<float>::round_style << endl;
    cout << "39 What is the rounding style for int? " <<
        (int)numeric_limits<int>::round_style << endl;
    cout << "40 How does a float represent a signaling NaN? " <<
        numeric_limits<float>::signaling_NaN() << endl;
    cout << "41 Is int specialized? " <<
        numeric_limits<float>::is_specialized << endl;
}

Program Output is:

 1 The minimum value for char is -128
 2 The minimum value for int is  -2147483648
 3 The maximum value for char is 127
 4 The maximum value for int is  2147483647
 5 The number of bits to represent a char is 7
 6 The number of bits to represent an int is 31
 7 The number of digits representable in base 10 for float is 6
 8 Is a char signed?              1
 9 Is an unsigned integer signed? 0
10 Is an integer an integer? 1
11 Is a float an integer?   0
12 Is an integer exact? 1
13 Is a float exact?  0
14 The radix for float is            2
15 The epsilon for float is          1.19209e-007
16 The round error for float is      0.5
17 The minimum exponent for float is -125
18 The minimum exponent in base 10   -37
19 The maximum exponent is           128
20 The maximum exponent in base 10   38
21 Can float represent positive infinity?  1
22 Can double represent positive infinity? 1
23 Can int represent positive infinity? 0
24 Can float represent a NaN?           1
25 Can float represent a signaling NaN? 1
26 Does float allow denormalized values?   1
27 Does float detect denormalization loss? 1
28 Representation of positive infinity for float 1.#INF
29 Representation of quiet NaN for float         -1.#IND
30 Minimum denormalized number for float         1.4013e-045
31 Minimum positive denormalized value for float 1.4013e-045
32 Does float adhere to IEC 559 standard?  1
33 Is float bounded? 1
34 Is float modulo?  0
35 Is int modulo?    0
36 Is trapping implemented for float?    1
37 Is tinyness detected before rounding? 1
38 What is the rounding style for float? 1
39 What is the rounding style for int? 0
40 How does a float represent a signaling NaN? -1.#INF
41 Is int specialized? 1


operator == and operator < deque (STL Sample)

The sample code below illustrates how to use the operator == and operator < deque STL functions in Visual C++.

Required Header:
< deque>

Prototype:

template<class T, class A>
     bool operator==(const deque <T, A>& lhs, const deque <T, A>& rhs);

template<class T, class A>
     bool operator<(const deque <T, A>& lhs, const deque <T, A>& rhs);

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
The first template function overloads operator== to compare two objects of template class deque. The function returns: lhs.size() == rhs.size() && equal(lhs. begin(), lhs. end(), rhs.begin()). For equality, the number of elements must be equal in both deque objects. The second template function overloads operator< to compare two objects of template class deque. The function returns: lexicographical_compare(lhs. begin(), lhs. end(), rhs.begin(), rhs.end()). Because lexicographic (as in a dictionary) compare is used, the number of elements does not matter while using operator<. In the sample code, adding a line of code while creating the b object, such as b.push_front('D');, will make b greater than a.

Sample Code:

//////////////////////////////////////////////////////////////////////
//
// Compile options needed: -GX
//
// deque.cpp :
//
// Functions:
//
//    ==
//    <
//
//////////////////////////////////////////////////////////////////////

/* Compile options needed:-GX
*/
#include <iostream>
#include <deque>

using namespace std;

typedef deque<char >  CHARDEQUE;
void print_contents (CHARDEQUE  deque, char*);

void main()
{
    //create a  with  3 A's
    CHARDEQUE  a(3,'A');
    a.push_front('C');

    //create b with 4 B's.
    CHARDEQUE  b(6,'B');

    //print out the contents
    print_contents (a,"a");
    print_contents (b,"b");

    //compare a and b
    if (a==b)
        cout <<"a is equal to b"<<endl;
    else if(a<b)
            cout <<"a is less than b"<<endl;
    else
        cout <<"a is greater than b" <<endl;

    //assign the contents of b to a
    a.assign(b.begin(),b.end());
    print_contents (a,"a");
    print_contents (b,"b");

    //compare a and b again
    if (a==b)
        cout <<"a is equal to b"<<endl;
    else if(a<b)
            cout <<"a is less than b"<<endl;
    else
        cout <<"a is greater than b" <<endl;

}

//function to print the contents of deque
void print_contents (CHARDEQUE  deque, char *name)
{
    CHARDEQUE::iterator pdeque;

    cout <<"The contents of "<< name <<" : ";

        for(pdeque = deque.begin();
        pdeque != deque.end();
        pdeque++)
    {
        cout << *pdeque <<" " ;
    }
        cout<<endl;
}

Program Output is:

The contents of a : C A A A
The contents of b : B B B B B B
a is greater than b
The contents of a : B B B B B B
The contents of b : B B B B B B
a is equal to b


Pair Logical Operator (STL Sample)

The sample code below illustrates how to use the pair logical operator STL function in Visual C++.

Required Header:
< utility >

Prototype:

It is interesting to note that only the < and == operators are
necessary in order to define all of the logical operators.

template<class _T1, class _T2> inline
     bool operator==(const pair<_T1, _T2>& _X,
     const pair<_T1, _T2>& _Y)
     {return (_X.first == _Y.first && _X.second == _Y.second); }

template<class _T1, class _T2> inline
     bool operator<(const pair<_T1, _T2>& _X,
     const pair<_T1, _T2>& _Y)
     {return (_X.first < _Y.first ||
     !(_Y.first < _X.first) && _X.second < _Y.second); }

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
The functions are described in the comments section of the sample.

Sample Code:

/////////////////////////////
// Compile options needed: none
//
// paircomp.cpp : Illustrates several comparison
//                operators used to compare two
//                pair objects.
//
// Functions:
//
//    operator== - returns true if two pair objects are identical.
//
//    operator!= - returns true if two pair objects are not identical.
//
//    operator<  - returns true for (A < B) if pair object A is less
//                 than pair object B.
//
//    operator<= - returns true for (A <= B) if pair object A is less
//                 than or equal to pair object B.
//
//    operator>  - returns true for (A > B) if pair object A is greater
//                 than pair object B.
//
//    operator>= - returns true for (A >= B) if pair object A is greater
//                 than or equal to pair object B.
/////////////////////////////

#include <iostream>
#include <utility>

using namespace std ;

/* STL pair data type containing int and float */

typedef struct pair<int, float> PAIR_IF;

void main(void)
{
  PAIR_IF A(10,3.14);
  PAIR_IF B(18,3.14);
  PAIR_IF C(10,6.28);
  PAIR_IF D(10,3.14);

/* show pair values */

  cout << "A = ( " << A.first << " , " << A.second << " )" << endl;
  cout << "B = ( " << B.first << " , " << B.second << " )" << endl;
  cout << "C = ( " << C.first << " , " << C.second << " )" << endl;
  cout << "D = ( " << D.first << " , " << D.second << " )" << endl;

/* operator== */

  if (A==D)
    cout << "A and D are equal" << endl;
  else
    cout << "A and D are not equal" << endl;

/* operator!= */

  if (B!=C)
    cout << "B and C are not equivalent" << endl;
  else
    cout << "B and C are equivalent" << endl;

/* operator> */

  if (A>C)
    cout << "A is greater than C" << endl;
  else
    cout << "A is not greater than C" << endl;

/* operator>= */

  if (A>=C)
    cout << "A is greater than or equal to C" << endl;
  else
    cout << "A is not greater than or equal to C" << endl;

/* operator< */

  if (C<D)
    cout << "C is less than D" << endl;
  else
    cout << "C is not less than D" << endl;

/* operator<= */

  if (C<D)
    cout << "C is less than or equal to D" << endl;
  else
    cout << "C is not less than or equal to D" << endl;
}

Program Output is:

A = ( 10 , 3.14 )
B = ( 18 , 3.14 )
C = ( 10 , 6.28 )
D = ( 10 , 3.14 )
A and D are equal
B and C are not equivalent
A is not greater than C
A is not greater than or equal to C
C is not less than D
C is not less than or equal to D


partial_sort (STL Sample)

The sample code below illustrates how to use the partial_sort STL function in Visual C++.

Required Header:
<algorithm>

Prototype:

template<class RandomAccessIterator> inline
     void partial_sort(RandomAccessIterator first,
     RandomAccessIterator middle,
     RandomAccessIterator last)

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
The partial_sort algorithm sorts the smallest N elements, where N = middle - first of the sequence [first, last). The remaining elements end up in the range [middle..last) in an undefined order. The non-predicate version of partial_sort uses operator< for comparisons.

Sample Code:

//////////////////////////////////////////////////////////////////////
//
// Compile options needed: /GX
//
// partial_sort.cpp : Illustrates how to use the partial_sort
//                    function.
//
// Functions:
//
//    partial_sort : Sort the smallest N elements in a sequence.
// Copyright (c) 1996 Microsoft Corporation. All rights reserved.
//////////////////////////////////////////////////////////////////////

// disable warning C4786: symbol greater than 255 character,
// okay to ignore
#pragma warning(disable: 4786)

#include <iostream>
#include <algorithm>
#include <functional>
#include <vector>

using namespace std ;

void main()
{
    const int VECTOR_SIZE = 8 ;

    // Define a template class vector of int
    typedef vector<int> IntVector ;

    //Define an iterator for template class vector of strings
    typedef IntVector::iterator IntVectorIt ;

    IntVector Numbers(VECTOR_SIZE) ;

    IntVectorIt start, end, it ;

    // Initialize vector Numbers
    Numbers[0] = 4 ;
    Numbers[1] = 10;
    Numbers[2] = 70 ;
    Numbers[3] = 30 ;
    Numbers[4] = 10;
    Numbers[5] = 69 ;
    Numbers[6] = 96 ;
    Numbers[7] = 7;

    start = Numbers.begin() ;   // location of first
                                // element of Numbers

    end = Numbers.end() ;       // one past the location
                                // last element of Numbers

    cout << "Before calling partial_sort\n" << endl ;

    // print content of Numbers
    cout << "Numbers { " ;
    for(it = start; it != end; it++)
        cout << *it << " " ;
    cout << " }\n" << endl ;

    // sort the smallest 4 elements in the sequence
    partial_sort(start, start+4, end) ;

    cout << "After calling partial_sort\n" << endl ;

    cout << "Numbers { " ;
    for(it = start; it != end; it++)
        cout << *it << " " ;
    cout << " }\n" << endl ;
}

Program Output is:

Before calling partial_sort

Numbers { 4 10 70 30 10 69 96 7  }

After calling partial_sort

Numbers { 4 7 10 10 70 69 96 30  }


partial_sort_copy (STL Sample)

The sample code below illustrates how to use the partial_sort_copy STL function in Visual C++.

Required Header:
<algorithm>

Prototype:

template<class InputIterator, RandomAccessIterator> inline
     RandomAccessIterator partial_sort(InputIterator first1,
     InputIterator last1,
     RandomAccessIterator first2,
     RandomAccessIterator last2)

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
The partial_sort_copy algorithm sorts the smallest N elements, where N = min((last1 - first1), (last2 - first2)), of the sequence [first1, last1) and copies the results to the sequence [first2, first2 + N]. The non-predicate version of partial_sort_copy uses operator< for comparisons.

Sample Code:

//////////////////////////////////////////////////////////////////////
//
// Compile options needed: /GX
//
// partial_sort_copy.cpp : Illustrates how to use the partial_sort_copy
//                         function.
//
// Functions:
//
//    partial_sort_copy : Sort the smallest N elements in a sequence
//                        and copy the resulting sequence
//                        to another sequence.
//////////////////////////////////////////////////////////////////////

// disable warning C4786: symbol greater than 255 character,
// okay to ignore
#pragma warning(disable: 4786)

#include <iostream>
#include <algorithm>
#include <functional>
#include <vector>

using namespace std ;

void main()
{
    const int VECTOR_SIZE = 8 ;

    // Define a template class vector of int
    typedef vector<int> IntVector ;

    //Define an iterator for template class vector of strings
    typedef IntVector::iterator IntVectorIt ;

    IntVector Numbers(VECTOR_SIZE) ;
    IntVector Result(4) ;

    IntVectorIt start, end, it ;

    // Initialize vector Numbers
    Numbers[0] = 4 ;
    Numbers[1] = 10;
    Numbers[2] = 70 ;
    Numbers[3] = 30 ;
    Numbers[4] = 10;
    Numbers[5] = 69 ;
    Numbers[6] = 96 ;
    Numbers[7] = 7;

    start = Numbers.begin() ;   // location of first
                                // element of Numbers

    end = Numbers.end() ;       // one past the location
                                // last element of Numbers

    cout << "Before calling partial_sort_copy\n" << endl ;

    // print content of Numbers
    cout << "Numbers { " ;
    for(it = start; it != end; it++)
        cout << *it << " " ;
    cout << " }\n" << endl ;

    // sort the smallest 4 elements in the Numbers
    // and copy the results in Result
    partial_sort_copy(start, end, Result.begin(), Result.end()) ;

    cout << "After calling partial_sort_copy\n" << endl ;

    cout << "Numbers { " ;
    for(it = start; it != end; it++)
        cout << *it << " " ;
    cout << " }\n" << endl ;

    cout << "Result { " ;
    for(it = Result.begin(); it != Result.end(); it++)
        cout << *it << " " ;
    cout << " }\n" << endl ;
}

Program Output is:

Before calling partial_sort_copy

Numbers { 4 10 70 30 10 69 96 7  }

After calling partial_sort_copy

Numbers { 4 10 70 30 10 69 96 7  }

Result { 4 7 10 10  }


Predicate Version of partial_sort_copy (STL Sample)

The sample code below illustrates how to use the predicate version of the partial_sort_copy STL function in Visual C++.

Required Header:
<algorithm>

Prototype:

template<class InputIterator, RandomAccessIterator, class Compare> inline
     RandomAccessIterator partial_sort(InputIterator first1,
     InputIterator last1,
     RandomAccessIterator first2,
     RandomAccessIterator last2,
     Compare compare)

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
The partial_sort_copy algorithm sorts the smallest N elements, where N = min((last1 - first1), (last2 - first2)), of the sequence [first1, last1), and copies the results to the sequence [first2, first2 + N]. The predicate version of partial_sort_copy uses the compare function for comparisons.

Sample Code:

//////////////////////////////////////////////////////////////////////
//
// Compile options needed: /GX
//
// partial_sort_copyP.cpp : Illustrates how to use the predicate version
//                          of the partial_sort_copy function.
//
// Functions:
//
//    partial_sort_copy : Sort the smallest N elements in a sequence
//                        and copy the resulting sequence
//                        to another sequence.
//////////////////////////////////////////////////////////////////////

// disable warning C4786: symbol greater than 255 character,
// okay to ignore
#pragma warning(disable: 4786)

#include <iostream>
#include <algorithm>
#include <functional>
#include <vector>

using namespace std ;

void main()
{
    const int VECTOR_SIZE = 8 ;

    // Define a template class vector of int
    typedef vector<int> IntVector ;

    //Define an iterator for template class vector of strings
    typedef IntVector::iterator IntVectorIt ;

    IntVector Numbers(VECTOR_SIZE) ;
    IntVector Result(4) ;

    IntVectorIt start, end, it ;

    // Initialize vector Numbers
    Numbers[0] = 4 ;
    Numbers[1] = 10;
    Numbers[2] = 70 ;
    Numbers[3] = 30 ;
    Numbers[4] = 10;
    Numbers[5] = 69 ;
    Numbers[6] = 96 ;
    Numbers[7] = 7;

    start = Numbers.begin() ;   // location of first
                                // element of Numbers

    end = Numbers.end() ;       // one past the location
                                // last element of Numbers

    cout << "Before calling partial_sort_copy\n" << endl ;

    // print content of Numbers
    cout << "Numbers { " ;
    for(it = start; it != end; it++)
        cout << *it << " " ;
    cout << " }\n" << endl ;

    // sort the smallest 4 elements in the Numbers
    // and copy the results in Result
    partial_sort_copy(start, end, Result.begin(),Result.end(),less<int>());

    cout << "After calling partial_sort_copy\n" << endl ;

    cout << "Numbers { " ;
    for(it = start; it != end; it++)
        cout << *it << " " ;
    cout << " }\n" << endl ;

    cout << "Result { " ;
    for(it = Result.begin(); it != Result.end(); it++)
        cout << *it << " " ;
    cout << " }\n" << endl ;
}

Program Output is:

Before calling partial_sort_copy

Numbers { 4 10 70 30 10 69 96 7  }

After calling partial_sort_copy

Numbers { 4 10 70 30 10 69 96 7  }

Result { 4 7 10 10  }


Predicate Version of partial_sort (STL Sample)

The sample code below illustrates how to use the predicate version of the partial_sort STL function in Visual C++.

Required Header:
<algorithm>

Prototype:

template<class RandomAccessIterator, class Compare> inline
     void partial_sort(RandomAccessIterator first,
     RandomAccessIterator middle,
     RandomAccessIterator last,
     Compare compare)

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
The partial_sort algorithm sorts the smallest N elements, where N = middle - first of the sequence [first, last). The remaining elements end up in the range [middle..last) in an undefined order. The predicate version of partial_sort uses the compare function for comparisons.

Sample Code:

//////////////////////////////////////////////////////////////////////
//
// Compile options needed: /GX
//
// partial_sort.cpp : Illustrates how to use the predicate version
//                    of the partial_sort function.
//
// Functions:
//
//    partial_sort : Sort the smallest N elements in a sequence.
//////////////////////////////////////////////////////////////////////

// disable warning C4786: symbol greater than 255 character,
// okay to ignore
#pragma warning(disable: 4786)

#include <iostream>
#include <algorithm>
#include <functional>
#include <vector>

using namespace std ;

void main()
{
    const int VECTOR_SIZE = 8 ;

    // Define a template class vector of int
    typedef vector<int> IntVector ;

    //Define an iterator for template class vector of strings
    typedef IntVector::iterator IntVectorIt ;

    IntVector Numbers(VECTOR_SIZE) ;

    IntVectorIt start, end, it ;

    // Initialize vector Numbers
    Numbers[0] = 4 ;
    Numbers[1] = 10;
    Numbers[2] = 70 ;
    Numbers[3] = 30 ;
    Numbers[4] = 10;
    Numbers[5] = 69 ;
    Numbers[6] = 96 ;
    Numbers[7] = 7;

    start = Numbers.begin() ;   // location of first
                                // element of Numbers

    end = Numbers.end() ;       // one past the location
                                // last element of Numbers

    cout << "Before calling partial_sort\n" << endl ;

    // print content of Numbers
    cout << "Numbers { " ;
    for(it = start; it != end; it++)
        cout << *it << " " ;
    cout << " }\n" << endl ;

    // sort the smallest 4 elements in the sequence
    partial_sort(start, start+4, end, less<int>()) ;

    cout << "After calling partial_sort\n" << endl ;

    cout << "Numbers { " ;
    for(it = start; it != end; it++)
        cout << *it << " " ;
    cout << " }\n" << endl ;
}

Program Output is:

Before calling partial_sort

Numbers { 4 10 70 30 10 69 96 7  }

After calling partial_sort

Numbers { 4 7 10 10 70 69 96 30  }


partial_sum (STL Sample)

The sample code below illustrates how to use the partial_sum STL function in Visual C++.

Required Header:
<numeric>

Prototype:

template<class InputIterator, class OutputIterator> inline
     OutputIterator partial_sum(InputIterator first, InputIterator last, OutputIterator first2)

template<class InputIterator, class OutputIterator, class BinaryOperator> inline
     OutputIterator partial_sum(InputIterator first, InputIterator last, OutputIterator first2,
     BinaryOperator binary_op)

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
Assigns to every iterator i in the range [result,result + (last - first)) a value correspondingly equal to ((...(*first + *(first + 1)) + ...) + *(first + (i - result))) - or - binary_op(binary_op(..., binary_op(*first, *(first + 1)),...), *(first + (i - result))). In other words, *(result+i) = init + *(first+0) + *(first+1) + ... + *(first+i).

Sample Code:

///////////////////////////////////////////////////////////////////////
//
// Compile options needed: /GX
//
// partial_sum.cpp : Demonstrates the use of partial_sum().
//
// Description of partial_sum(first,last,first2,init)
//                partial_sum(first,last,first2,init,binary_op):
//
//    Assigns to every iterator i in the range
//    [result,result + (last - first)) a value correspondingly equal to
//    ((...(*first + *(first + 1)) + ...) + *(first + (i - result)))
//
//     - or -
//
//    binary_op(binary_op(..., binary_op(*first, *(first  +  1)),...),
//    *(first + (i - result)))
//
//    In other words,
//    *(result+i) = init + *(first+0) + *(first+1) + ... + *(first+i)
///////////////////////////////////////////////////////////////////////

#include <iostream>
#include <numeric>
#include <functional>
#include <vector>
#include <iterator>

using namespace std;

typedef vector < int > IntArray;
typedef ostream_iterator < int, char, char_traits<char> > IntOstreamIt;

void main ()
{
    IntOstreamIt itOstream(cout," ");

    // Initialize the array
    IntArray rgI;
    for (int i=1; i<=10; i++) rgI.push_back(i);

    // Print the arrays
    cout << "Array: ";
    copy(rgI.begin(),rgI.end(),itOstream);
    cout << endl;

    // The result array must be at least the same size as the data array
    IntArray rgIresult(rgI.size());

    // Compute the partial sum of the array
    partial_sum(rgI.begin(),rgI.end(),rgIresult.begin());

    // Print the array of partial sums
    cout << "Array of partial sums: ";
    copy(rgIresult.begin(),rgIresult.end(),itOstream);
    cout << endl;

    // Compute the partial product of the array
    partial_sum(rgI.begin(),rgI.end(),rgIresult.begin(),multiplies<int>());

    // Print the array of partial products
    cout << "Array of partial products: ";
    partial_sum(rgIresult.begin(),rgIresult.end(),itOstream);
    cout << endl;
}

Program Output is:

Array: 1 2 3 4 5 6 7 8 9 10
Array of partial sums: 1 3 6 10 15 21 28 36 45 55
Array of partial products: 1 3 9 33 153 873 5913 46233 409113 4037913


partition (STL Sample)

The sample code below illustrates how to use the partition STL function in Visual C++.

Required Header:
<algorithm>

Prototype:

template<class BidirectionalIterator, class Predicate> inline
     BidirectionalIterator partition(BidirectionalIterator first, BidirectionalIterator last, Predicate predicate)

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
The partition algorithm arranges elements in the range [first, last) such that the elements for which predicate returns true are before the elements for which predicate returns false. The algorithm returns an iterator positioned at the first element for which predicate returns false.

Sample Code:

//////////////////////////////////////////////////////////////////////
//
// Compile options needed: /GX
//
// partition.cpp : Illustrates how to use the partition function.
//
// Functions:
//
//   partition  - Partition a range using a predicate.
//
//   begin      - Returns an iterator that points to the first element
//                in a sequence.
//
//   end        - Returns an iterator that points one past the end of
//                a sequence.
//
//   bind2nd    - Returns true for elements for which the condition
//                is true.
//////////////////////////////////////////////////////////////////////

// disable warning C4786: symbol greater than 255 character,
// okay to ignore
#pragma warning(disable: 4786)

#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>

using namespace std;

void main()
{
    const int VECTOR_SIZE = 8 ;

    // Define a template class vector of integers
    typedef vector<int > IntVector ;

    //Define an iterator for template class vector of integer
    typedef IntVector::iterator IntVectorIt ;

    IntVector Numbers(VECTOR_SIZE) ;   //vector containing numbers

    IntVectorIt start, end, it ;

    start = Numbers.begin() ;   // location of first
                                // element of Numbers

    end = Numbers.end() ;       // one past the location
                                // last element of Numbers

    //Initialize vector Numbers
    Numbers[0] = 6 ;
    Numbers[1] = 20 ;
    Numbers[2] = 10 ;
    Numbers[3] = 15 ;
    Numbers[4] = 12 ;
    Numbers[5] = 7 ;
    Numbers[6] = 9 ;
    Numbers[7] = 10 ;

    cout << "Before calling partition" << endl ;

    // print content of Numbers
    cout << "Numbers { " ;
    for(it = start; it != end; it++)
        cout << *it << " " ;
    cout << " }\n" << endl ;

    // partition the sequence such that all the elements
    // less than 11 appear before all the elements greater than 11
    it =  partition(start, end, bind2nd(less<int>(), 11)) ;

    cout << "After calling partition" << endl ;

    // print content of Numbers
    cout << "Numbers { " ;
    for(it = start; it != end; it++)
        cout << *it << " " ;
    cout << " }\n" << endl ;

}

Program Output is:

Before calling partition
Numbers { 6 20 10 15 12 7 9 10  }

After calling partition
Numbers { 6 10 10 9 7 12 15 20  }


prev_permutation (STL Sample)

The sample code below illustrates how to use the prev_permutation STL function in Visual C++.

Required Header:
<algorithm>

Prototype:

template<class BidirectionalIterator> inline
     bool prev_permutation(BidirectionalIterator first,
     BidirectionalIterator last)

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
The prev_permutation algorithm changes the order of the elements the range [first, last), to the previous lexicographic permutation and returns true. If there is no prev_permutation, it arranges the sequence to be the first permutation and returns false. IMPORTANT: The prev_permutation algorithm assumes the sequence is sorted in descending order using operator<. The non-predicate version uses the operator< to order the permutations.

Sample Code:

//////////////////////////////////////////////////////////////////////
//
// Compile options needed: /GX
//
// prev_permutation.cpp : Illustrates how to use the prev_permutation
//                        function.
//
// Functions:
//
//    prev_permutation : Change the order of the sequence to the
//                       previous lexicographic permutation.
//////////////////////////////////////////////////////////////////////

// disable warning C4786: symbol greater than 255 character,
// okay to ignore
#pragma warning(disable: 4786)

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <functional>

using namespace std ;

void main()
{
    const int VECTOR_SIZE = 3 ;

    // Define a template class vector of strings
    typedef vector<string> StrVector ;

    //Define an iterator for template class vector of strings
    typedef StrVector::iterator StrVectorIt ;

    //Define an ostream iterator for strings
    typedef ostream_iterator<string>
    StrOstreamIt;

    StrVector Pattern(VECTOR_SIZE) ;

    StrVectorIt start, end, it ;

    StrOstreamIt outIt(cout, " ") ;

    start = Pattern.begin() ;   // location of first
                                      // element of Pattern

    end = Pattern.end() ;       // one past the location last
                                       // element of Pattern

    //Initialize vector Pattern
    Pattern[0] = "C" ;
    Pattern[1] = "B" ;
    Pattern[2] = "A" ;

    // print content of Pattern
    cout << "Before calling prev_permutation...\n" << "Pattern: " ;
    for(it = start; it != end; it++)
        cout << *it << " " ;
    cout << "\n\n" ;

    // Generate all possible permutations

    cout << "After calling prev_permutation...." << endl ;
    while ( prev_permutation(start, end) )
    {
        copy(start, end, outIt) ;
        cout << endl ;
    }
}

Program Output is:

Before calling prev_permutation...
Pattern: C B A

After calling prev_permutation....
C A B
B C A
B A C
A C B
A B C


priority_queue functions (STL Sample)

The sample code below illustrates how to use the priority_queue::push, pop, empty, and top STL functions in Visual C++.

Required Header:
<queue>

Prototype:

     priority_queue::push();
     priority_queue::pop();
     priority_queue::empty();
     priority_queue::top();
     priority_queue::size();

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
The sample shows priority_queue implementation using deque and vector containers.

Sample Code:

//////////////////////////////////////////////////////////////////////
//
// Compile options needed: /GX
//
// <filename> :  priority_queue.cpp
//
// Functions:
//
//    priority_queue::push(), priority_queue::pop(),
//    priority_queue::empty(), priority_queue::top(), queue::size()
//
//////////////////////////////////////////////////////////////////////

#include <iostream>
#include <queue>
#include <deque>
#include <vector>
#include <functional>

using namespace std ;

// Using priority_queue with deque
// Use of function greater sorts the items in ascending order
typedef deque<int> INTDQU;
typedef priority_queue<int> INTPRQUE;

// Using priority_queue with vector
// Use of function less sorts the items in descending order
typedef vector<char> CHVECTOR;
typedef priority_queue<char> CHPRQUE;

void main(void)
{
    int size_q;
    INTPRQUE   q;
    CHPRQUE    p;

    // Insert items in the priority_queue(uses deque)
    q.push(42);
    q.push(100);
    q.push(49);
    q.push(201);

Program Output is:

    // Output the size of priority_queue
    size_q = q.size();
    cout << "size of q is:" << size_q << endl;

   // Output items in priority_queue using top()
    // and use pop() to get to next item until
    // priority_queue is empty
    while (!q.empty())
    {
        cout << q.top() << endl;
        q.pop();

    }

// Insert items in the priority_queue(uses vector)
    p.push('c');
    p.push('a');
    p.push('d');
    p.push('m');
    p.push('h');

    // Output the item at the top using top()
    cout << p.top() << endl;

    // Output the size of priority_queue
    size_q = p.size();
    cout << "size of p is:" << size_q << endl;

    // Output items in priority_queue using top()
    // and use pop() to get to next item until
    // priority_queue is empty
    while (!p.empty())
    {
        cout << p.top() << endl;
        p.pop();

    }
}

Program Output:

42
size of q is:4
42
49
100
201
m
size of p is:5
m
h
d
c
a


queue functions (STL Sample)

The sample code below illustrates how to use the queue::(push,pop,empty,back,front) STL functions in Visual C++.

Required Header:
<queue>

Prototype:

     queue::push();
     queue::pop();
     queue::empty();
     queue::back();
     queue::front();
     queue::size();

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
The sample shows queue implementation using list and deque containers.

Sample Code:

//////////////////////////////////////////////////////////////////////
//
// Compile options needed: none
//
// <filename> :  queue.cpp
//
// Functions:
//
//    queue::push(), queue::pop(), queue::empty(), queue::back(),
//    queue::front(),queue::size()
//
//////////////////////////////////////////////////////////////////////

/* Compile options needed:none
*/
#include <list>
#include <iostream>
#include <queue>
#include <deque>

using namespace std ;

// Using queue with list
typedef list<int > INTLIST;
typedef queue<int>  INTQUEUE;

// Using queue with deque
typedef deque<char*> CHARDEQUE;
typedef queue<char*> CHARQUEUE;

void main(void)
{
    int size_q;
    INTQUEUE q;
    CHARQUEUE p;

    // Insert items in the queue(uses list)
    q.push(42);
    q.push(100);
    q.push(49);
    q.push(201);

Program Output is:

    // Output the size of queue
    size_q = q.size();
    cout << "size of q is:" << size_q << endl;

    // Output items in queue using front()
    // and use pop() to get to next item until
    // queue is empty
    while (!q.empty())
    {
        cout << q.front() << endl;
        q.pop();

    }

// Insert items in the queue(uses deque)
    p.push("cat");
    p.push("ape");
    p.push("dog");
    p.push("mouse");
    p.push("horse");

    // Output the item inserted last using back()
    cout << p.back() << endl;

    // Output the size of queue
    size_q = p.size();
    cout << "size of p is:" << size_q << endl;

    // Output items in queue using front()
    // and use pop() to get to next item until
    // queue is empty
    while (!p.empty())
    {
        cout << p.front() << endl;
        p.pop();

    }
}

Program Output:

201
size of q is:4
42
100
49
201
horse
size of p is:5
cat
ape
dog
mouse
horse


random_shuffle (STL Sample)

The sample code below illustrates how to use the random_shuffle STL function in Visual C++.

Required Header:
<algorithm>

Prototype:

template<class RandomAccessIterator> inline
     void random_shuffle(RandomAccessIterator first,
     RandomAccessIterator last)

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
The random_shuffle algorithm shuffles the elements of a sequence [first..last) in a random order. The non-predicate version uses an internal random-number generator to generate the indices of the elements to swap. The non-predicate version of random_shuffle uses operator= to perform swaps.

Sample Code:

//////////////////////////////////////////////////////////////////////
//
// Compile options needed: /GX
//
// random_shuffle.cpp : Illustrates how to use the random_shuffle
//                      function.
//
// Functions:
//
//     random_shuffle : Shuffle the elements in a random order.
//////////////////////////////////////////////////////////////////////

// disable warning C4786: symbol greater than 255 character,
// okay to ignore
#pragma warning(disable: 4786)

#include <iostream>
#include <algorithm>
#include <functional>
#include <vector>

using namespace std ;

void main()
{
    const int VECTOR_SIZE = 8 ;

    // Define a template class vector of int
    typedef vector<int> IntVector ;

    //Define an iterator for template class vector of strings
    typedef IntVector::iterator IntVectorIt ;

    IntVector Numbers(VECTOR_SIZE) ;

    IntVectorIt start, end, it ;

    // Initialize vector Numbers
    Numbers[0] = 4 ;
    Numbers[1] = 10;
    Numbers[2] = 70 ;
    Numbers[3] = 30 ;
    Numbers[4] = 10;
    Numbers[5] = 69 ;
    Numbers[6] = 96 ;
    Numbers[7] = 100;

    start = Numbers.begin() ;   // location of first
                                // element of Numbers

    end = Numbers.end() ;       // one past the location
                                // last element of Numbers

    cout << "Before calling random_shuffle\n" << endl ;

    // print content of Numbers
    cout << "Numbers { " ;
    for(it = start; it != end; it++)
        cout << *it << " " ;
    cout << " }\n" << endl ;

    // shuffle the elements in a random order
    random_shuffle(start, end) ;

    cout << "After calling random_shuffle\n" << endl ;

    cout << "Numbers { " ;
    for(it = start; it != end; it++)
        cout << *it << " " ;
    cout << " }\n" << endl ;
}

Program Output is:

Before calling random_shuffle

Numbers { 4 10 70 30 10 69 96 100  }

After calling random_shuffle

Numbers { 10 30 4 70 96 100 69 10  }


Predicate Version of random_shuffle (STL Sample)

The sample code below illustrates how to use the predicate version of the random_shuffle STL function in Visual C++.

Required Header:
<algorithm>

Prototype:

template<class RandomAccessIterator, class Predicate> inline
     void random_shuffle(RandomAccessIterator first, RandomAccessIterator last, Predicate pred)

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
The random_shuffle algorithm shuffles the elements of a sequence [first..last) in a random order. The predicate version uses the pred function to generate the indices of the elements to swap. The pred has to be a function object that takes a parameter n and returns an integral random number in the range 0 - (n - 1). The predicate version of random_shuffle uses operator= to perform swaps.

Sample Code:

//////////////////////////////////////////////////////////////////////
//
// Compile options needed: /GX
//
// random_shuffle.cpp: Illustrates how to use the predicate version
//                      of the random_shuffle function.
//
// Functions:
//
//    random_shuffle: Shuffle the elements in a random order.
//
//      Rand: Given n, generates an integral random number in the
//          in the range 0 - (n - 1).
//////////////////////////////////////////////////////////////////////

// disable warning C4786: symbol greater than 255 character,
// okay to ignore
#pragma warning(disable: 4786)

#include <iostream>
#include <algorithm>
#include <functional>
#include <vector>

using namespace std;

// return an integral random number in the range 0 - (n - 1)
int Rand(int n)
{
    return rand() % n ;
}

void main()
{
    const int VECTOR_SIZE = 8 ;

    // Define a template class vector of int
    typedef vector<int > IntVector ;

    //Define an iterator for template class vector of strings
    typedef IntVector::iterator IntVectorIt ;

    IntVector Numbers(VECTOR_SIZE) ;

    IntVectorIt start, end, it ;

    // Initialize vector Numbers
    Numbers[0] = 4 ;
    Numbers[1] = 10;
    Numbers[2] = 70 ;
    Numbers[3] = 30 ;
    Numbers[4] = 10;
    Numbers[5] = 69 ;
    Numbers[6] = 96 ;
    Numbers[7] = 100;

    start = Numbers.begin() ;   // location of first
                                // element of Numbers

    end = Numbers.end() ;       // one past the location
                                // last element of Numbers

    cout << "Before calling random_shuffle:\n" << endl ;

    // print content of Numbers
    cout << "Numbers { " ;
    for(it = start; it != end; it++)
        cout << *it << " " ;
    cout << " }\n" << endl ;

    // shuffle the elements in a random order.
    // the pointer_to_unary_function adapter converts a function to a
    // function object.
    random_shuffle(start, end, pointer_to_unary_function<int, int>(Rand));

    cout << "After calling random_shuffle:\n" << endl ;

    cout << "Numbers { " ;
    for(it = start; it != end; it++)
        cout << *it << " " ;
    cout << " }\n" << endl ;
}

Program Output is:

Before calling random_shuffle

Numbers { 4 10 70 30 10 69 96 100  }

After calling random_shuffle

Numbers { 10 30 4 70 96 100 69 10  }


remove (STL Sample)

The sample code below illustrates how to use the remove STL function in Visual C++.

Required Header:
<algorithm>

Prototype:

template<class ForwardIterator, class Type> inline
     ForwardIterator remove(ForwardIterator first, ForwardIterator last, const T& value)

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
The remove algorithm removes all elements that match value from the range (first, last). It returns an iterator equal to last - N, where N = number of elements removed. The last N elements of the range have undefined values. The size of the container remains the same.

Sample Code:

//////////////////////////////////////////////////////////////////////
//
// Compile options needed: /GX
//
// remove.cpp : Illustrates how to use the remove function.
//
// Functions:
//
//   remove - remove all elements from the sequence that match value.
//   begin - Returns an iterator that points to the first element in a
//           sequence.
//   end - Returns an iterator that points one past the end of a sequence.
//////////////////////////////////////////////////////////////////////

// disable warning C4786: symbol greater than 255 character,
// okay to ignore
#pragma warning(disable: 4786)

#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>

using namespace std;

void main()
{
    const int VECTOR_SIZE = 8 ;

    // Define a template class vector of integers
    typedef vector<int > IntVector ;

    //Define an iterator for template class vector of integer
    typedef IntVector::iterator IntVectorIt ;

    IntVector Numbers(VECTOR_SIZE) ;   //vector containing numbers

    IntVectorIt start, end, it, last;

    start = Numbers.begin() ;   // location of first
                                // element of Numbers

    end = Numbers.end() ;       // one past the location
                                // last element of Numbers

    //Initialize vector Numbers
    Numbers[0] = 10 ;
    Numbers[1] = 20 ;
    Numbers[2] = 10 ;
    Numbers[3] = 15 ;
    Numbers[4] = 12 ;
    Numbers[5] = 7 ;
    Numbers[6] = 9 ;
    Numbers[7] = 10 ;

    cout << "Before calling remove" << endl ;

    // print content of Numbers
    cout << "Numbers { " ;
    for(it = start; it != end; it++)
        cout << *it << " " ;
    cout << " }\n" << endl ;

    // remove all elements from Numbers that match 10
     last = remove(start, end, 10) ;

    cout << "After calling remove" << endl ;

    // print content of Numbers
    cout << "Numbers { " ;
    for(it = start; it != end; it++)
        cout << *it << " " ;
    cout << " }\n" << endl ;

    //print number of elements removed from Numbers
    cout << "Total number of elements removed from Numbers = "
        << end - last << endl ;

    //print only the valid elements of Number
    cout << "Valid elements of Numbers { " ;
    for(it = start; it != last; it++)
        cout << *it << " " ;
    cout << " }\n" << endl ;

}

Program Output is:

Before calling remove
Numbers { 10 20 10 15 12 7 9 10  }

After calling remove
Numbers { 20 15 12 7 9 7 9 10  }

Total number of elements removed from Numbers = 3
Valid elements of Numbers { 20 15 12 7 9  }


remove_copy (STL Sample)

The sample code below illustrates how to use the remove_copy STL function in Visual C++.

Required Header:
<algorithm>

Prototype:

template<class ForwardIterator, class OutputIterator, class Type> inline
     OutputIterator remove_copy(ForwardIterator first, ForwardIterator last,
     OutputIterator result, const T& value)

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
The remove_copy algorithm copies all elements from the range (first, last) to the range starting at result, skipping any element that matches value. It returns an iterator positioned immediately after the last new element.

Sample Code:

//////////////////////////////////////////////////////////////////////
//
// Compile options needed: /GX
//
// remove_copy.cpp : Illustrates how to use the remove_copy function.
//
// Functions:
//
//   remove_copy - copy the elements of a sequence to another sequence
//                 eliminating any elements that match value.
//   begin - Returns an iterator that points to the first element in a
//           sequence.
//   end - Returns an iterator that points one past the end of a sequence.
//////////////////////////////////////////////////////////////////////

// disable warning C4786: symbol greater than 255 character,
// okay to ignore
#pragma warning(disable: 4786)

#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>

using namespace std;

void main()
{
   const int MAX_ELEMENTS = 8 ;

   // Define a template class vector of integers
   typedef vector<int > IntVector ;

   //Define an iterator for template class vector of integer
   typedef IntVector::iterator IntVectorIt ;

   //vector containing numbers
   IntVector Numbers(MAX_ELEMENTS), Result(MAX_ELEMENTS) ;

   IntVectorIt start, end, it, last, resultIt ;

   //Initialize vector Numbers
   Numbers[0] = 10 ;
   Numbers[1] = 20 ;
      Numbers[2] = 10 ;
   Numbers[3] = 15 ;
   Numbers[4] = 12 ;
   Numbers[5] = 7 ;
   Numbers[6] = 9 ;
   Numbers[7] = 10 ;

   start = Numbers.begin() ;   // location of first
                               // element of Numbers

   end = Numbers.end() ;       // one past the location
                               // last element of Numbers

   resultIt = Result.begin() ; // location of first
                               // element of Result

   // print content of Numbers
   cout << "Numbers { " ;
   for(it = start; it != end; it++)
      cout << *it << " " ;
   cout << " }\n" << endl ;

   // copy all elements from Numbers to Result
   // skipping any item that equals 10
   last = remove_copy(start, end, resultIt, 10) ;

   //print number of elements copied to Result
   cout << "Total number of elements copied to Result = "
      << last - resultIt << endl ;

   start = Result.begin() ;   // location of first
                               // element of Result

   end = Result.end() ;       // one past the location
                              // last element of Result

   // print content of Result
   cout << "Result { " ;
   for(it = start; it != end; it++)
      cout << *it << " " ;
   cout << " }\n" << endl ;
}

Program Output is:

Numbers { 10 20 10 15 12 7 9 10  }

Total number of elements copied to Result = 5
Result { 20 15 12 7 9 0 0 0  }


remove_copy_if (STL Sample)

The sample code below illustrates how to use the remove_copy_if STL function in Visual C++.

Required Header:
<algorithm>

Prototype:

template<class ForwardIterator, class OutputIterator, class Predicate>
     inline OutputIterator remove_copy_if(ForwardIterator first, ForwardIterator last,
    OutputIterator result, Predicate pred)

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
The remove_copy_if algorithm copies all elements from the range (first, last) to the range starting at result, skipping any element that causes the predicate to return true. It returns an iterator positioned immediately after the last new element.

Sample Code:

//////////////////////////////////////////////////////////////////////
//
// Compile options needed: /GX
//
// remove_copy_if.cpp : Illustrates how to use the remove_copy_if function.
//
// Functions:
//
//   remove_copy_if - copy the elements of a sequence to another sequence
//                    eliminating any elements that satisfy a predicate.
//   bind2nd - Returns true for elements for which the condition is true
//   begin - Returns an iterator that points to the first element in a
//           sequence
//   end - Returns an iterator that points one past the end of a sequence
//////////////////////////////////////////////////////////////////////

// disable warning C4786: symbol greater than 255 characters,
// okay to ignore
#pragma warning(disable: 4786)

#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>

using namespace std;

void main()
{
    const int MAX_ELEMENTS = 8 ;

    // Define a template class vector of integers
    typedef vector<int > IntVector ;

    //Define an iterator for template class vector of integer
    typedef IntVector::iterator IntVectorIt ;

    //vector containing numbers
    IntVector Numbers(MAX_ELEMENTS), Result(MAX_ELEMENTS) ;

    IntVectorIt start, end, it, last, resultIt ;

    //Initialize vector Numbers
    Numbers[0] = 10 ;
    Numbers[1] = 20 ;
    Numbers[2] = 10 ;
    Numbers[3] = 15 ;
    Numbers[4] = 12 ;
    Numbers[5] = 25 ;
    Numbers[6] = 30 ;
    Numbers[7] = 10 ;

    start = Numbers.begin() ;   // location of first
                                // element of Numbers

    end = Numbers.end() ;       // one past the location
                                // last element of Numbers

    resultIt = Result.begin() ; // location of first
                                // element of Result

    // print content of Numbers
    cout << "Numbers { " ;
    for(it = start; it != end; it++)
        cout << *it << " " ;
    cout << " }\n" << endl ;

    // copy all elements from Numbers to Result
    // skipping any item that >= 25
    last = remove_copy_if(start, end, resultIt,
                          bind2nd(greater_equal<int>(), 25)) ;

    //print number of elements copied to Result
    cout << "Total number of elements copied to Result = "
        << last - resultIt << endl ;

    start = Result.begin() ;   // location of first
                                // element of Result

    end = Result.end() ;       // one past the location
                               // last element of Result

    // print content of Result
    cout << "Result { " ;
    for(it = start; it != end; it++)
        cout << *it << " " ;
    cout << " }\n" << endl ;
}

Program Output is:

Numbers { 10 20 10 15 12 25 30 10  }

Total number of elements copied to Result = 6
Result { 10 20 10 15 12 10 0 0  }


remove_if (STL Sample)

The sample code below illustrates how to use the remove_if STL function in Visual C++.

Required Header:
<algorithm>

Prototype:

template<class ForwardIterator, class Predicate> inline
     ForwardIterator remove_if(ForwardIterator first, ForwardIterator last, Predicate pred)

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
The remove_if algorithm removes all elements from the range (first, last) that cause the predicate to return true. It returns an iterator equal to last - N, where N = number of elements removed. The last N elements of the range have undefined values. The size of the container remains the same.

Sample Code:

//////////////////////////////////////////////////////////////////////
//
// Compile options needed: /GX
//
// remove_if.cpp : Illustrates how to use the remove_if function.
//
// Functions:
//
//   remove_if - remove all elements from the sequence that
//               satisfies a predicate.
//   bind2nd - Returns true for elements for which the condition is true
//   begin - Returns an iterator that points to the first element in a
//           sequence
//   end - Returns an iterator that points one past the end of a sequence
//////////////////////////////////////////////////////////////////////

// disable warning C4786: symbol greater than 255 character,
// okay to ignore
#pragma warning(disable: 4786)

#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>

using namespace std;

void main()
{
    const int VECTOR_SIZE = 8 ;

    // Define a template class vector of integers
    typedef vector<int > IntVector ;

    //Define an iterator for template class vector of integer
    typedef IntVector::iterator IntVectorIt ;

    IntVector Numbers(VECTOR_SIZE) ;   //vector containing numbers

    IntVectorIt start, end, it, last;

    start = Numbers.begin() ;   // location of first
                                // element of Numbers

    end = Numbers.end() ;       // one past the location
                                // last element of Numbers

    //Initialize vector Numbers
    Numbers[0] = 10 ;
    Numbers[1] = 20 ;
    Numbers[2] = 10 ;
    Numbers[3] = 15 ;
    Numbers[4] = 12 ;
    Numbers[5] = 7 ;
    Numbers[6] = 9 ;
    Numbers[7] = 10 ;

    cout << "Before calling remove_if" << endl ;

    // print content of Numbers
    cout << "Numbers { " ;
    for(it = start; it != end; it++)
        cout << *it << " " ;
    cout << " }\n" << endl ;

    // remove all elements from Numbers that <= 10
     last = remove_if(start, end, bind2nd(less_equal<int>(), 10) ) ;

    cout << "After calling remove_if" << endl ;

    // print content of Numbers
    cout << "Numbers { " ;
    for(it = start; it != end; it++)
        cout << *it << " " ;
    cout << " }\n" << endl ;

    //print number of elements removed from Numbers
    cout << "Total number of elements removed from Numbers = "
        << end - last << endl ;

    //print only the valid elements of Number
    cout << "Valid elements of Numbers { " ;
    for(it = start; it != last; it++)
        cout << *it << " " ;
    cout << " }\n" << endl ;

}

Program Output is:

Before calling remove_if
Numbers { 10 20 10 15 12 7 9 10  }

After calling remove_if
Numbers { 20 15 12 15 12 7 9 10  }

Total number of elements removed from Numbers = 5
Valid elements of Numbers { 20 15 12  }


replace (STL Sample)

The sample code below illustrates how to use the replace STL function in Visual C++.

Required Header:
<algorithm>

Prototype:

template<class ForwardIterator, class Type> inline
void remove(ForwardIterator first, ForwardIterator last,
     const T& old_value, const T& new_value)

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
The replace algorithm replaces all elements that match old_value from the range [first, last) with new_value.

Sample Code:

//////////////////////////////////////////////////////////////////////
//
// Compile options needed: /GX
//
// replace.cpp : Illustrates how to use the replace function.
//
// Functions:
//
//    replace - Replace all elements from the sequence that match value
//              with another value.
//
//////////////////////////////////////////////////////////////////////

// disable warning C4786: symbol greater than 255 characters,
// okay to ignore
#pragma warning(disable: 4786)

#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>

using namespace std;

void main()
{
    const int VECTOR_SIZE = 8 ;

    // Define a template class vector of integers
    typedef vector<int > IntVector ;

    //Define an iterator for template class vector of integer
    typedef IntVector::iterator IntVectorIt ;

    IntVector Numbers(VECTOR_SIZE) ;   //vector containing numbers

    IntVectorIt start, end, it ;

    start = Numbers.begin() ;   // location of first
                                // element of Numbers

    end = Numbers.end() ;       // one past the location
                                // last element of Numbers

    //Initialize vector Numbers
    Numbers[0] = 10 ;
    Numbers[1] = 20 ;
    Numbers[2] = 10 ;
    Numbers[3] = 15 ;
    Numbers[4] = 12 ;
    Numbers[5] = 7 ;
    Numbers[6] = 9 ;
    Numbers[7] = 10 ;

    cout << "Before calling replace" << endl ;

    // print content of Numbers
    cout << "Numbers { " ;
    for(it = start; it != end; it++)
        cout << *it << " " ;
    cout << " }\n" << endl ;

    // remove all elements from Numbers that match 10
     replace(start, end, 10, 35) ;

    cout << "After calling replace, to replace all 10's with 35" << endl ;

    // print content of Numbers
    cout << "Numbers { " ;
    for(it = start; it != end; it++)
        cout << *it << " " ;
    cout << " }\n" << endl ;

}

Program Output is:

Before calling replace
Numbers { 10 20 10 15 12 7 9 10  }

After calling replace, to replace all 10's with 35
Numbers { 35 20 35 15 12 7 9 35  }


replace_copy (STL Sample)

The sample code below illustrates how to use the replace_copy STL function in Visual C++.

Required Header:
<algorithm>

Prototype:

template<class ForwardIterator, class OutputIterator, class Type> inline
      OutputIterator replace_copy(ForwardIterator first, ForwardIterator last,
      OutputIterator result, const T& old_value, const T& new_value)

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
The replace_copy algorithm copies all elements from the range [first, last) to a same-size range starting at result, replacing all occurrences of old_value with new_value in the resulting sequence. It returns an iterator positioned immediately after the last new element in the resulting sequence.

Sample Code:

//////////////////////////////////////////////////////////////////////
//
// Compile options needed: /GX
//
// replace_copy.cpp : Illustrates how to use the replace_copy function.
//
// Functions:
//
//    replace_copy - Copy the elements of a sequence to another
//                   same-size sequence replacing any elements
//                   that match a value with another value.
//
//////////////////////////////////////////////////////////////////////

// disable warning C4786: symbol greater than 255 characters,
// okay to ignore
#pragma warning(disable: 4786)

#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>

using namespace std;

void main()
{
    const int MAX_ELEMENTS = 8 ;

    // Define a template class vector of integers
    typedef vector<int > IntVector ;

    //Define an iterator for template class vector of integer
    typedef IntVector::iterator IntVectorIt ;

    //vector containing numbers
    IntVector Numbers(MAX_ELEMENTS), Result(MAX_ELEMENTS) ;

    IntVectorIt start, end, it, last, resultIt ;

    //Initialize vector Numbers
    Numbers[0] = 10 ;
    Numbers[1] = 20 ;
    Numbers[2] = 10 ;
    Numbers[3] = 15 ;
    Numbers[4] = 12 ;
    Numbers[5] = 7 ;
    Numbers[6] = 9 ;
    Numbers[7] = 10 ;

    start = Numbers.begin() ;   // location of first
                                // element of Numbers

    end = Numbers.end() ;       // one past the location
                                // last element of Numbers

    resultIt = Result.begin() ; // location of first
                                // element of Result

    // print content of Numbers
    cout << "Numbers { " ;
    for(it = start; it != end; it++)
        cout << *it << " " ;
    cout << " }\n" << endl ;

    // copy all elements from Numbers to Result
    // replacing any item that equals 10 with 30
    last = replace_copy(start, end, resultIt, 10, 30) ;

    //print number of elements copied to Result
    cout << "Total number of elements copied to Result = "
        << last - resultIt << endl ;

    start = Result.begin() ;   // location of first
                                // element of Result

    end = Result.end() ;       // one past the location
                               // last element of Result

    // print content of Result
    cout << "Result  { " ;
    for(it = start; it != end; it++)
        cout << *it << " " ;
    cout << " }\n" << endl ;

}

Program Output is:

Numbers { 10 20 10 15 12 7 9 10  }

Total number of elements copied to Result = 8
Result  { 30 20 30 15 12 7 9 30  }


replace_copy_if (STL Sample)

The sample code below illustrates how to use the replace_copy_if STL function in Visual C++.

Required Header:
<algorithm>

Prototype:

template<class ForwardIterator, class OutputIterator, class Predicate, class Type> inline
     OutputIterator replace_copy_if(ForwardIterator first, ForwardIterator last, OutputIterator result,
     Predicate pred, const T& new_value)

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
The replace_copy_if algorithm copies all elements from the range [first, last) to a same-size range starting at result, replacing all occurrences that cause the predicate to return true with new_value in the resulting sequence. It returns an iterator positioned immediately after the last new element in the resulting sequence.

Sample Code:

//////////////////////////////////////////////////////////////////////
//
// Compile options needed: /GX
//
// replace_copy_if.cpp : Illustrates how to use the replace_copy_if
//                       function.
//
// Functions:
//
//    replace_copy_if - Copy the elements of a sequence to another
//                      same-size sequence replacing any elements
//                      that satisfies a predicate, with another value.
//
//////////////////////////////////////////////////////////////////////

// disable warning C4786: symbol greater than 255 characters,
// okay to ignore
#pragma warning(disable: 4786)

#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>

using namespace std;

void main()
{
    const int MAX_ELEMENTS = 8 ;

    // Define a template class vector of integers
    typedef vector<int > IntVector ;

    //Define an iterator for template class vector of integer
    typedef IntVector::iterator IntVectorIt ;

    //vector containing numbers
    IntVector Numbers(MAX_ELEMENTS), Result(MAX_ELEMENTS) ;

    IntVectorIt start, end, it, last, resultIt ;

    //Initialize vector Numbers
    Numbers[0] = 10 ;
    Numbers[1] = 20 ;
    Numbers[2] = 10 ;
    Numbers[3] = 15 ;
    Numbers[4] = 12 ;
    Numbers[5] = 7 ;
    Numbers[6] = 9 ;
    Numbers[7] = 10 ;

    start = Numbers.begin() ;   // location of first
                                // element of Numbers

    end = Numbers.end() ;       // one past the location
                                // last element of Numbers

    resultIt = Result.begin() ; // location of first
                                // element of Result

    // print content of Numbers
    cout << "Numbers { " ;
    for(it = start; it != end; it++)
        cout << *it << " " ;
    cout << " }\n" << endl ;

    // copy all elements from Numbers to Result
    // replacing any item that >= 10 with 30
    last = replace_copy_if(start, end, resultIt,
                           bind2nd(greater_equal<int>(), 10), 30) ;

    //print number of elements copied to Result
    cout << "Total number of elements copied to Result = "
        << last - resultIt << endl ;

    start = Result.begin() ;   // location of first
                                // element of Result

    end = Result.end() ;       // one past the location
                               // last element of Result

    // print content of Result
    cout << "Result  { " ;
    for(it = start; it != end; it++)
        cout << *it << " " ;
    cout << " }\n" << endl ;

}

Program Output is:

Numbers { 10 20 10 15 12 7 9 10  }

Total number of elements copied to Result = 8
Result  { 30 30 30 30 30 7 9 30  }


replace_if (STL Sample)

The sample code below illustrates how to use the replace_if STL function in Visual C++.

Required Header:
<algorithm>

Prototype:

template<class ForwardIterator, class Predicate, class Type> inline
     void replace_if(ForwardIterator first, ForwardIterator last, Predicate pred, const Type& value)

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
The replace_if algorithm replaces all elements from the range [first, last) that cause the predicate to return true with value.

Sample Code:

//////////////////////////////////////////////////////////////////////
//
// Compile options needed: /GX
//
// replace_if.cpp : Illustrates how to use the replace_if function.
//
// Functions:
//
//    replace_if - Replace all elements from the sequence that
//                 satisfies a predicate with a specified value.
//
//////////////////////////////////////////////////////////////////////

// disable warning C4786: symbol greater than 255 characters,
// okay to ignore
#pragma warning(disable: 4786)

#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>

using namespace std;

void main()
{
    const int VECTOR_SIZE = 8 ;

    // Define a template class vector of integers
    typedef vector<int > IntVector ;

    //Define an iterator for template class vector of integer
    typedef IntVector::iterator IntVectorIt ;

    IntVector Numbers(VECTOR_SIZE) ;   //vector containing numbers

    IntVectorIt start, end, it ;

    start = Numbers.begin() ;   // location of first
                                // element of Numbers

    end = Numbers.end() ;       // one past the location
                                // last element of Numbers

    //Initialize vector Numbers
    Numbers[0] = 10 ;
    Numbers[1] = 20 ;
    Numbers[2] = 10 ;
    Numbers[3] = 15 ;
    Numbers[4] = 12 ;
    Numbers[5] = 7 ;
    Numbers[6] = 9 ;
    Numbers[7] = 10 ;

    cout << "Before calling replace_if" << endl ;

    // print content of Numbers
    cout << "Numbers { " ;
    for(it = start; it != end; it++)
        cout << *it << " " ;
    cout << " }\n" << endl ;

    // replace all elements from Numbers that are <= 10 with 4
     replace_if(start, end, bind2nd(less_equal<int>(), 10), 4 ) ;

    cout << "After calling replace_if" << endl ;

    // print content of Numbers
    cout << "Numbers { " ;
    for(it = start; it != end; it++)
        cout << *it << " " ;
    cout << " }\n" << endl ;

}

Program Output is:

Before calling replace_if
Numbers { 10 20 10 15 12 7 9 10  }

After calling replace_if
Numbers { 4 20 4 15 12 4 4 4  }


reverse (STL Sample)

The sample code below illustrates how to use the reverse STL function in Visual C++.

Required Header:
<algorithm>

Prototype:

template<class BidirectionalIterator> inline
     void reverse(BidirectionalIterator first, BidirectionalIterator last)

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
The reverse algorithm reverses the order of the elements in the range [first, last).

Sample Code:

//////////////////////////////////////////////////////////////////////
//
// Compile options needed: /GX
//
// reverse.cpp : Illustrates how to use the reverse function.
//
// Functions:
//
//    reverse - Reverse the items in a sequence.
//
//////////////////////////////////////////////////////////////////////

// disable warning C4786: symbol greater than 255 character,
// okay to ignore
#pragma warning(disable: 4786)

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <functional>

using namespace std;

void main()
{
    const int VECTOR_SIZE = 8 ;

    // Define a template class vector of strings
    typedef vector<string > StrVector ;

    //Define an iterator for template class vector of strings
    typedef StrVector::iterator StrVectorIt ;

    StrVector Tongue_Twister(VECTOR_SIZE) ;

    StrVectorIt start, end, it ;

    start = Tongue_Twister.begin() ;   // location of first
                                      // element of Tongue_Twister

    end = Tongue_Twister.end() ;       // one past the location last
                                       // element of Tongue_Twister

    //Initialize vector Tongue_Twister
    Tongue_Twister[0] = "she" ;
    Tongue_Twister[1] = "sells" ;
    Tongue_Twister[2] = "sea" ;
    Tongue_Twister[3] = "shells" ;
    Tongue_Twister[4] = "by";
    Tongue_Twister[5] = "the";
    Tongue_Twister[6] = "sea" ;
    Tongue_Twister[7] = "shore" ;

    cout << "Before calling reverse \n" << endl ;

    // print content of Tongue_Twister
    cout << "Try this Tongue Twister: " ;
    for(it = start; it != end; it++)
        cout << *it << " " ;
    cout << "\n\n" ;

    // reverse the items in the vector Tongue_Twister
     reverse(start, end) ;

     cout << "After calling reverse \n" << endl ;

    // print content of Tongue_Twister
    cout << "Now try the reversed Tongue Twister: " ;
    for(it = start; it != end; it++)
        cout << *it << " " ;
    cout << "\n\n" ;

}

Program Output is:

Before calling reverse

Try this Tongue Twister: she sells sea shells by the sea shore

After calling reverse

Now try the reversed Tongue Twister: shore sea the by shells sea sells she


reverse_copy (STL Sample)

The sample code below illustrates how to use the reverse_copy STL function in Visual C++.

Required Header:
<algorithm>

Prototype:

template<class BidirectionalIterator, class OutputIterator> inline
     OutputIterator reverse_copy(BidirectionalIterator first,
     BidirectionalIterator last,
     OutputIterator result)

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
The reverse_copy algorithm reverses the order of the elements in the range [first, last) and copies the result into a sequence of the same size starting at result. It returns an iterator positioned immediately after the last new element in the resulting sequence.

Sample Code:

//////////////////////////////////////////////////////////////////////
//
// Compile options needed: /GX
//
// reverse_copy.cpp : Illustrates how to use the reverse_copy function.
//
// Functions:
//
//    reverse_copy - Reverse a sequence, copy the results to another
//                   same-sized sequence.
//
//////////////////////////////////////////////////////////////////////

// disable warning C4786: symbol greater than 255 character,
// okay to ignore
#pragma warning(disable: 4786)

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <functional>

using namespace std ;

void main()
{
    const int VECTOR_SIZE = 8 ;

    // Define a template class vector of strings
    typedef vector<string> StrVector ;

    //Define an iterator for template class vector of strings
    typedef StrVector::iterator StrVectorIt ;

    StrVector Tongue_Twister(VECTOR_SIZE) ;
    StrVector Reversed_Twister(VECTOR_SIZE) ;

    StrVectorIt start, end, it, RTstart, RTend ;

    start = Tongue_Twister.begin() ; // location of first
                                     // element of Tongue_Twister

    end = Tongue_Twister.end() ;     // one past the location last
                                     // element of Tongue_Twister

    RTstart = Reversed_Twister.begin() ; // location of first
                                         // element of Reversed_Twister

    RTend = Reversed_Twister.end() ; // one past the location last
                                     // element of Reversed_Twister

    //Initialize vector Tongue_Twister
    Tongue_Twister[0] = "she" ;
    Tongue_Twister[1] = "sells" ;
    Tongue_Twister[2] = "sea" ;
    Tongue_Twister[3] = "shells" ;
    Tongue_Twister[4] = "by";
    Tongue_Twister[5] = "the";
    Tongue_Twister[6] = "sea" ;
    Tongue_Twister[7] = "shore" ;

    cout << "Before calling reverse_copy \n" << endl ;

    // print content of Tongue_Twister
    cout << "Try this Tongue Twister: " ;
    for(it = start; it != end; it++)
        cout << *it << " " ;
    cout << "\n\n" ;

    // reverse the items in the vector Tongue_Twister
    // and copy the results to Reversed_Twister
     reverse_copy(start, end, RTstart) ;

     cout << "After calling reverse_copy: \n"
         << endl ;

    // print content of Tongue_Twister
    cout << "Tongue_Twister: " ;
    for(it = start; it != end; it++)
        cout << *it << " " ;
    cout << "\n\n" ;

    // print content of Reversed_Twister
    cout << "Now try the reversed Tongue Twister: " ;
    for(it = RTstart; it != RTend; it++)
        cout << *it << " " ;
    cout << "\n\n" ;

}

Program Output is:

Before calling reverse_copy

Try this Tongue Twister: she sells sea shells by the sea shore

After calling reverse_copy:

Tongue_Twister: she sells sea shells by the sea shore

Now try the reversed Tongue Twister: shore sea the by shells sea sells she


rotate (STL Sample)

The sample code below illustrates how to use the rotate STL function in Visual C++.

Required Header:
<algorithm>

Prototype:

template<class ForwardIterator> inline
     void rotate(ForwardIterator first,
     ForwardIterator middle,
     ForwardIterator last)

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
The rotate algorithm rotates the elements in the range [first, last) to the right by N positions, where N = middle - first.

Sample Code:

//////////////////////////////////////////////////////////////////////
//
// Compile options needed: /GX
//
// rotate.cpp : Illustrates how to use the rotate function.
//
// Functions:
//
//    rotate - Rotate the items in a sequence by n positions.
//
//////////////////////////////////////////////////////////////////////

// disable warning C4786: symbol greater than 255 character,
// okay to ignore
#pragma warning(disable: 4786)

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <functional>

using namespace std ;

void main()
{
    const int VECTOR_SIZE = 8 ;

    // Define a template class vector of strings
    typedef vector<string> StrVector ;

    //Define an iterator for template class vector of strings
    typedef StrVector::iterator StrVectorIt ;

    StrVector Tongue_Twister(VECTOR_SIZE) ;

    StrVectorIt start, end, middle, it ;

    start = Tongue_Twister.begin() ;   // location of first
                                       // element of Tongue_Twister

    end = Tongue_Twister.end() ;       // one past the location last
                                       // element of Tongue_Twister

    //Initialize vector Tongue_Twister
    Tongue_Twister[0] = "she" ;
    Tongue_Twister[1] = "sells" ;
    Tongue_Twister[2] = "sea" ;
    Tongue_Twister[3] = "shells" ;
    Tongue_Twister[4] = "by";
    Tongue_Twister[5] = "the";
    Tongue_Twister[6] = "sea" ;
    Tongue_Twister[7] = "shore" ;

    middle = start + 3 ;  // start position for rotating elements

    cout << "Before calling rotate\n" << endl ;

    // print content of Tongue_Twister
    cout << "Try this Tongue Twister: " ;
    for(it = start; it != end; it++)
        cout << *it << " " ;
    cout << "\n\n" ;

    // rotate the items in the vector Tongue_Twister by 3 positions
    rotate(start, middle, end) ;

    cout << "After calling rotate \n" << endl ;

    // print content of Tongue_Twister
    cout << "Now try the rotated Tongue Twister: " ;
    for(it = start; it != end; it++)
        cout << *it << " " ;
    cout << "\n\n" ;
}

Program Output is:

Before calling rotate

Try this Tongue Twister: she sells sea shells by the sea shore

After calling rotate

Now try the rotated Tongue Twister: shells by the sea shore she sells sea


rotate_copy (STL Sample)

The sample code below illustrates how to use the rotate_copy STL function in Visual C++.

Required Header:
<algorithm>

Prototype:

template<class ForwardIterator, class OutputIterator> inline
     OutputIterator rotate_copy(BidirectionalIterator first,
     BidirectionalIterator middle,
     BidirectionalIterator last,
     OutputIterator result)

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
The rotate_copy algorithm rotates the elements in the range [first, last) to the right by N positions (where N = middle - first), and copies the result into a sequence of the same size, starting at result. It returns an iterator positioned immediately after the last new element in the resulting sequence. Note that the OutputIterator should be different from the sequence to be rotated. If they are the same, the result will depend on the implementation.

Sample Code:

//////////////////////////////////////////////////////////////////////
//
// Compile options needed: /GX
//
// rotate_copy.cpp : Illustrates how to use the rotate_copy function.
//
// Functions:
//
//    rotate_copy - Rotate a sequence by n positions, copy the
//                  results to another same sized sequence.
//
//////////////////////////////////////////////////////////////////////

// disable warning C4786: symbol greater than 255 character,
// okay to ignore
#pragma warning(disable: 4786)

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <functional>

using namespace std ;

void main()
{
    const int VECTOR_SIZE = 8 ;

    // Define a template class vector of strings
    typedef vector<string> StrVector ;

    //Define an iterator for template class vector of strings
    typedef StrVector::iterator StrVectorIt ;

    StrVector Tongue_Twister(VECTOR_SIZE) ;
    StrVector Rotated_Twister(VECTOR_SIZE) ;

    StrVectorIt start, middle, end, it, RTstart, RTend ;

    start = Tongue_Twister.begin() ;    // location of first
                                        // element of Tongue_Twister

    end = Tongue_Twister.end() ;        // one past the location last
                                        // element of Tongue_Twister

    middle = start + 3 ;                // start position for
                                        // rotating elements

    RTstart = Rotated_Twister.begin() ; // location of first
                                        // element of Rotated_Twister

    RTend = Rotated_Twister.end() ;     // one past the location last
                                        // element of Rotated_Twister

    //Initialize vector Tongue_Twister
    Tongue_Twister[0] = "she" ;
    Tongue_Twister[1] = "sells" ;
    Tongue_Twister[2] = "sea" ;
    Tongue_Twister[3] = "shells" ;
    Tongue_Twister[4] = "by";
    Tongue_Twister[5] = "the";
    Tongue_Twister[6] = "sea" ;
    Tongue_Twister[7] = "shore" ;

    cout << "Before calling rotate_copy:\n" << endl ;

    // print content of Tongue_Twister
    cout << "Try this Tongue Twister: " ;
    for(it = start; it != end; it++)
        cout << *it << " " ;
    cout << "\n\n" ;

    // rotate the items in the vector Tongue_Twist to the right by
    // 3 positions and copy the results to Rotated_Twister
    rotate_copy(start, middle, end, RTstart) ;

    cout << "After calling rotate_copy:\n" << endl ;

    // print content of Tongue_Twister
    cout << "Tongue_Twister: " ;
    for(it = start; it != end; it++)
        cout << *it << " " ;
    cout << "\n\n" ;

    // print content of Rotated_Twister
    cout << "Now try the rotated Tongue Twister: " ;
    for(it = RTstart; it != RTend; it++)
        cout << *it << " " ;
    cout << "\n\n" ;
}

Program Output is:

Before calling rotate_copy:

Try this Tongue Twister: she sells sea shells by the sea shore

After calling rotate_copy:

Tongue_Twister: she sells sea shells by the sea shore

Now try the rotated Tongue Twister: shells by the sea shore she sells sea


set::(lower_, upper_)bound, equal_range (STL Sample)

The sample code below illustrates how to use the set::lower_bound, set::upper_bound, and set::equal_range STL functions in Visual C++.

Required Header:
<set>

Prototype:

template<class _K, class _Pr, class _A>
     class set
     {
        public:
        // Function 1:
        const_iterator lower_bound(const _K& _Kv) const;
        // Function 2:
        const_iterator upper_bound(const _K& _Kv) const;
        // Function 3:
        _Paircc equal_range(const _K& _Kv) const;
     }

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
The lower_bound function returns an iterator to the earliest element in the controlled sequence that has a key that does not match the value passed to the lower_bound function. The upper_bound function returns an iterator to the earliest element in the controlled sequence that has a key matching the value passed to the upper_bound function. If no such element exists, the function returns end(). In both cases, the function set::key_comp()(key, x) is used to determine if the keys match. The equal_range function returns a pair value, where .first is the result of the lower_bound function, and .second is the result of the upper_bound function.

Sample Code:

//////////////////////////////////////////////////////////////////////
//
// Compile options needed: -GX
//
// SetBoundRange.cpp:
//      Illustrates how to use the lower_bound function to get an
//      iterator to the earliest element in the controlled sequence
//      that has a key that does not match the value passed to the
//      function. It also illustrates how to use the upper_bound
//      function to get an iterator to the earliest element in the
//      controlled sequence that has a key that matches the value
//      passed to the function. The last thing it illustrates is
//      how to use the equal_range function to get a pair value that
//      contains the lower_bound and upper_bound results of the key.
//
// Functions:
//
//    lower_bound  Returns an iterator whose value does not match the
//                 key passed to the function, or end() if no such
//                 element exists.
//    upper_bound  Returns an iterator whose value matches the key
//                 passed to the function, or end() if no such element
//                 exists.
//    equal_range  Returns a pair of (lower_bound,upper_bound).
//////////////////////////////////////////////////////////////////////

#pragma warning(disable:4786)
#include <set>
#include <iostream>

using namespace std ;

typedef set<int> SET_INT;

void main() {
  SET_INT s1;
  SET_INT::iterator i;
  cout << "s1.insert(5)" << endl;
  s1.insert(5);
  cout << "s1.insert(10)" << endl;
  s1.insert(10);
  cout << "s1.insert(15)" << endl;
  s1.insert(15);
  cout << "s1.insert(20)" << endl;
  s1.insert(20);
  cout << "s1.insert(25)" << endl;
  s1.insert(25);

  cout << "s1 -- starting at s1.lower_bound(12)" << endl;
// prints: 15,20,25
  for (i=s1.lower_bound(12);i!=s1.end();i++)
     cout << "s1 has " << *i << " in its set." << endl;

  cout << "s1 -- starting at s1.lower_bound(15)" << endl;
// prints: 15,20,25
  for (i=s1.lower_bound(15);i!=s1.end();i++)
     cout << "s1 has " << *i << " in its set." << endl;

  cout << "s1 -- starting at s1.upper_bound(12)" << endl;
// prints: 15,20,25
  for (i=s1.upper_bound(12);i!=s1.end();i++)
     cout << "s1 has " << *i << " in its set." << endl;

  cout << "s1 -- starting at s1.upper_bound(15)" << endl;
// prints: 20,25
  for (i=s1.upper_bound(15);i!=s1.end();i++)
     cout << "s1 has " << *i << " in its set." << endl;

  cout << "s1 -- s1.equal_range(12)" << endl;
// does not print anything
  for (i=s1.equal_range(12).first;i!=s1.equal_range(12).second;i++)
     cout << "s1 has " << *i << " in its set." << endl;

  cout << "s1 -- s1.equal_range(15)" << endl;
// prints: 15
  for (i=s1.equal_range(15).first;i!=s1.equal_range(15).second;i++)
     cout << "s1 has " << *i << " in its set." << endl;
}

Program Output is:

s1.insert(5)
s1.insert(10)
s1.insert(15)
s1.insert(20)
s1.insert(25)
s1 -- starting at s1.low
s1 has 15 in its set.
s1 has 20 in its set.
s1 has 25 in its set.
s1 -- starting at s1.low
s1 has 15 in its set.
s1 has 20 in its set.
s1 has 25 in its set.
s1 -- starting at s1.upp
s1 has 15 in its set.
s1 has 20 in its set.
s1 has 25 in its set.
s1 -- starting at s1.upp
s1 has 20 in its set.
s1 has 25 in its set.
s1 -- s1.equal_range(12)
s1 -- s1.equal_range(15)
s1 has 15 in its set.


set::(key_, value_)comp (STL Sample)

The sample code below illustrates how to use the set::key_comp and set::value_comp STL functions in Visual C++.

Required Header:
<set>

Prototype:

template<class _K, class _Pr, class _A>
     class set
     {
         public:
        // Function 1:
        key_compare key_comp() const;
        // Function 2:
        value_compare value_comp() const;
     }

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
The key_comp function returns the stored function object that determines the order of elements in the controlled sequence. The value_comp function returns the same function that key_comp returns.

Sample Code:

//////////////////////////////////////////////////////////////////////
//
// Compile options needed: -GX
//
// SetComp.cpp:
//      Illustrates how to use the key_comp function to obtain a
//      function pointer that is the stored function object that
//      determines the order of elements in the controlled sequence.
//      It also illustrates how to use the value_comp function to
//      obtain a function pointer that is the stored function object
//      that determines the order of the elements in the controlled
//      sequence (same as key_comp result).
//
// Functions:
//
//    key_comp     Returns a function pointer to the function that
//                 determines the order of elements in the controlled
//                 sequence.
//    value_comp   Returns a function pointer to the function that
//                 determines the order of elements in the controlled
//                 sequence (same as key_comp).
//////////////////////////////////////////////////////////////////////

#pragma warning(disable:4786)
#include <set>
#include <iostream>

using namespace std ;

typedef set<int> SET_INT;

void truefalse(int x)
{
  cout << (x?"True":"False") << endl;
}

void main() {
  SET_INT s1;

  cout << "s1.key_comp()(8,10) returned ";
  truefalse(s1.key_comp()(8,10));  // True

  cout << "s1.value_comp()(8,10) returned ";
  truefalse(s1.value_comp()(8,10));  // True

  cout << "s1.key_comp()(10,8) returned ";
  truefalse(s1.key_comp()(10,8));  // False

  cout << "s1.value_comp()(10,8) returned ";
  truefalse(s1.value_comp()(10,8));  // False

  cout << "s1.key_comp()(8,8) returned ";
  truefalse(s1.key_comp()(8,8));  // False

  cout << "s1.value_comp()(8,8) returned ";
  truefalse(s1.value_comp()(8,8));   // False
}

Program Output is:

s1.key_comp()(8,10) returned True
s1.value_comp()(8,10) returned True
s1.key_comp()(10,8) returned False
s1.value_comp()(10,8) returned False
s1.key_comp()(8,8) returned False
s1.value_comp()(8,8) returned False


set::count (STL Sample)

The sample code below illustrates how to use the set::count STL function in Visual C++.

Required Header:
<set>

Prototype:

template<class _K, class _Pr, class _A>
     class set
     {
         public:
         // Function 1:
         size_type count(const _K& _Kv) const;
     }

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
The count function is used to determine the number of elements in the controlled sequence that have a particular key.

Sample Code:

//////////////////////////////////////////////////////////////////////
//
// Compile options needed: -GX
//
// SetCount.cpp:
//      Illustrates how to use the count function to determine how
//      many elements have a particular key.
//
// Functions:
//
//    count        Returns the number of elements in the controlled
//                 sequence that have a particular key.
//////////////////////////////////////////////////////////////////////

#pragma warning(disable:4786)
#include <set>
#include <iostream>

using namespace std ;

typedef set<int> SET_INT;

void truefalse(int x)
{
  cout << (x?"True":"False") << endl;
}

void main() {
  SET_INT s1;
  SET_INT::_Pairib pib;
  cout << "s1.insert(5)" << endl;
  pib=s1.insert(5);
  cout << "Inserted element: ";
  truefalse(pib.second);  // True

  cout << "s1.insert(5)" << endl;
  pib=s1.insert(5);
  cout << "Inserted element: ";
  truefalse(pib.second);  // True

  cout << "s1.insert(8)" << endl;
  s1.insert(8);

  cout << "s1.insert(12)" << endl;
  s1.insert(12);

  cout << "s1.count(5) returned ";
  cout << s1.count(5) << endl;    // 1

  cout << "s1.count(9) returned ";
  cout << s1.count(9) << endl;    // 0
}

Program Output is:

s1.insert(5)
Inserted element: True
s1.insert(5)
Inserted element: False
s1.insert(8)
s1.insert(12)
s1.count(5) returned 1
s1.count(9) returned 0


set::empty and set::clear (STL Sample)

The sample code below illustrates how to use the set::empty and set::clear STL functions in Visual C++.

Required Header:
<set>

Prototype:

template<class _K, class _Pr, class _A>
     class set
     {
        public:
        // Function 1:
        bool empty() const;
        // Function 2:
        void clear();
     }

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
The empty function returns true when there are no elements in the controlled sequence. By calling erase(begin,end), the clear function removes all elements in the controlled sequence. For more information on the erase function, see set::erase.

Sample Code:

//////////////////////////////////////////////////////////////////////
//
// Compile options needed: -GX
//
// SetEmpty&Clear.cpp:
//      Illustrates how to use the empty function to determine if
//      there are elements in the controlled sequence. It also
//      illustrates how to use the clear function to remove all
//      elements from the controlled sequence.
//
// Functions:
//
//    empty        Returns true if there are no elements in the
//                 controlled sequence.
//    clear        Removes all elements from the controlled sequence.
//////////////////////////////////////////////////////////////////////

#pragma warning(disable:4786)
#include <set>
#include <iostream>

using namespace std ;

typedef set<int> SET_INT;

void truefalse(int x)
{
  cout << (x?"True":"False") << endl;
}

void main() {
  SET_INT s1;

  cout << "s1.empty() returned ";
  truefalse(s1.empty());  // True

  cout << "s1.insert(5)" << endl;
  s1.insert(5);
  cout << "s1.insert(8)" << endl;
  s1.insert(8);

  cout << "s1.empty() returned ";
  truefalse(s1.empty());  // False

  cout << "s1.clear()" << endl;
  s1.clear();

  cout << "s1.empty() returned ";
  truefalse(s1.empty());  // True
}

Program Output is:

s1.empty() returned True
s1.insert(5)
s1.insert(8)
s1.empty() returned False
s1.clear()
s1.empty() returned True


set::find (STL Sample)

The sample code below illustrates how to use the set::find STL function in Visual C++.

Required Header:
<set>

Prototype:

template<class _K, class _Pr, class _A>
     class set
     {
        public:
        // Function 1:
        const_iterator find(const _K& _Kv) const;
     }

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
The find function is used to locate an element in a controlled sequence. It returns an iterator to the first element in the controlled sequence whose sort key matches its parameter. If no such element exists, the returned iterator equals end().

Sample Code:

//////////////////////////////////////////////////////////////////////
//
// Compile options needed: -GX
//
// SetFind.cpp:
//      Illustrates how to use the find function to get an iterator
//      that points to the first element in the controlled sequence
//      that has a particular sort key.
//
// Functions:
//
//    find         Returns an iterator that points to the first element
//                 in the controlled sequence that has the same sort key
//                 as the value passed to the find function. If no such
//                 element exists, the iterator equals end().
//////////////////////////////////////////////////////////////////////

#pragma warning(disable:4786)
#include <set>
#include <iostream>

using namespace std ;

typedef set<int> SET_INT;

void truefalse(int x)
{
  cout << (x?"True":"False") << endl;
}

void main() {
  SET_INT s1;
  cout << "s1.insert(5)" << endl;
  s1.insert(5);
  cout << "s1.insert(8)" << endl;
  s1.insert(8);
  cout << "s1.insert(12)" << endl;
  s1.insert(12);

  SET_INT::iterator it;
  cout << "it=find(8)" << endl;
  it=s1.find(8);
  cout << "it!=s1.end() returned ";
  truefalse(it!=s1.end());  //  True

  cout << "it=find(6)" << endl;
  it=s1.find(6);
  cout << "it!=s1.end() returned ";
  truefalse(it!=s1.end());  // False
}

Program Output is:

s1.insert(5)
s1.insert(8)
s1.insert(12)
it=find(8)
it!=s1.end() returned True
it=find(6)
it!=s1.end() returned False


set::max_size (STL Sample)

The sample code below illustrates how to use the set::max_size STL function in Visual C++.

Required Header:
<set>

Prototype:

template<class _K, class _Pr, class _A>
     class set
     {
        public:
        // Function 1:
        size_type max_size() const;
     }

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
The max_size function is used to determine the maximum number of elements the controlled sequence can contain.

Sample Code:

//////////////////////////////////////////////////////////////////////
//
// Compile options needed: -GX
//
// SetMax_size.cpp:
//      Illustrates how to use the max_size function to determine how
//      many elements the controlled sequence can contain.
//
// Functions:
//
//    max_size     Returns the maximum number of elements the controlled
//                 sequence can contain.
//
//////////////////////////////////////////////////////////////////////

#pragma warning(disable:4786)
#include <set>
#include <iostream>
#include <assert.h>

using namespace std ;

typedef set<int> SET_INT;

void main() {
  SET_INT s1;

  cout << "s1.max_size() returned ";
  cout << s1.max_size() << endl;  // 1073741823 [value may vary]
  for (int x=0;(x<1000 && x<s1.max_size());x++)
   assert(s1.insert(x).second);
  cout << "s1.size() returned ";
  cout << s1.size() << endl; // 1000
}

Program Output is:

s1.max_size() returned 1073741823
s1.size() returned 1000


set::rbegin and set::rend (STL Sample)

The sample code below illustrates how to use the set::rbegin and set::rend STL functions in Visual C++.

Required Header:
<set>

Prototype:

template<class _K, class _Pr, class _A>
     class set
     {
         public:
         // Function 1:
         const_reverse_iterator rbegin() const;
         // Function 2:
         const_reverse_iterator rend() const;
     }

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
The rbegin function returns a reverse bidirectional iterator that points just beyond the end of the controlled sequence. The rend function returns a reverse bidirectional iterator that points at the first element of the sequence.

Sample Code:

//////////////////////////////////////////////////////////////////////
//
// Compile options needed: -GX
//
// SetRbeginRend.cpp:
//      Illustrates how to use the rbegin function to get a reverse
//      bidirectional iterator that points just beyond the end of
//      the controlled sequence. It also illustrates how to use
//      the rend function to get a reverse bidirectional iterator
//      that points at the first element of the sequence.
//
// Functions:
//
//    rbegin      Returns a reverse bidirectional iterator that points
//                just beyond the end of the controlled sequence.
//    rend        Returns a reverse bidirectional iterator that points
//                at the first element of the sequence.
//
//////////////////////////////////////////////////////////////////////

#pragma warning(disable:4786)
#include <set>
#include <iostream>

using namespace std ;

typedef set<int> SET_INT;

void main() {
  SET_INT s1;
  SET_INT::reverse_iterator i;
  cout << "s1.insert(5)" << endl;
  s1.insert(5);
  cout << "s1.insert(10)" << endl;
  s1.insert(10);
  cout << "s1.insert(15)" << endl;
  s1.insert(15);
  cout << "s1.insert(20)" << endl;
  s1.insert(20);

  // displays: 20,15,10,5
  for (i=s1.rbegin();i!=s1.rend();i++)
     cout << "s1 has " << *i << " in its set." << endl;
}

Program Output is:

s1.insert(5)
s1.insert(10)
s1.insert(15)
s1.insert(20)
s1 has 20 in its set.
s1 has 15 in its set.
s1 has 10 in its set.
s1 has 5 in its set.


set::size (STL Sample)

The sample code below illustrates how to use the set::size STL function in Visual C++.

Required Header:
<set>

Prototype:

template<class _K, class _Pr, class _A>
     class set
     {
         public:
         // Function 1:
         size_type size() const;
     }

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
The size function is used to determine the number of elements in the controlled sequence.

Sample Code:

//////////////////////////////////////////////////////////////////////
//
// Compile options needed: -GX
//
// SetSize.cpp:
//      Illustrates how to use the size function to determine how
//      many elements are in the controlled sequence.
//
// Functions:
//
//    size         Returns the number of elements in the controlled
//                 sequence.
//
//////////////////////////////////////////////////////////////////////

#pragma warning(disable:4786)
#include <set>
#include <iostream>

using namespace std ;

typedef set<int> SET_INT;

void main() {
  SET_INT s1;

  cout << "s1.size() returned ";
  cout << s1.size() << endl;  // 0

  cout << "s1.insert(5)" << endl;
  s1.insert(5);
  cout << "s1.insert(8)" << endl;
  s1.insert(8);
  cout << "s1.insert(12)" << endl;
  s1.insert(12);

  cout << "s1.size() returned ";
  cout << s1.size() << endl; // 3
}

Program Output is:

s1.size() returned 0
s1.insert(5)
s1.insert(8)
s1.insert(12)
s1.size() returned 3


set::swap, begin, end (STL Sample)

The sample code below illustrates how to use the set::(swap, begin, end) STL functions in Visual C++.

Required Header:
<set>

Prototype:

template<class _K, class _Pr, class _A>
    class set
    {
        public:
        // Function 1:
        void swap(_Myt& _X);
        // Function 2:
        friend void swap(_Myt& _X, _Myt& _Y);
        // Function 3:
        const_iterator begin() const;
        // Function 4:
        const_iterator end() const;
     }

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
The swap function swaps the two controlled sequences. The begin function returns a bidirectional iterator that points at the first element of the sequence. The end function returns a bidirectional iterator that points just beyond the end of the sequence.

Sample Code:

//////////////////////////////////////////////////////////////////////
//
// Compile options needed: -GX
//
// SetSwapBeginEnd.cpp:
//      Illustrates how to use the swap function to exchange the two
//      controlled sequences. It also illustrates how to use the
//      begin function to get a bidirectional iterator that points at
//      the first element of the controlled sequence. Finally, it
//      illustrates how to use the end function to get a bidirectional
//      iterator that points just beyond the end of the controlled
//      sequence.
//
// Functions:
//
//    swap        Exchanges the two controlled sequences.
//    begin       Returns a bidirectional iterator that points at the
//                first element of the controlled sequence.
//    end         Returns a bidirectional iterator that points just
//                beyond the end of the controlled sequence.
//
//////////////////////////////////////////////////////////////////////

#pragma warning(disable:4786)
#include <set>
#include <iostream>

using namespace std ;

typedef set<int> SET_INT;

void main() {
  SET_INT s1;
  SET_INT s2;
  SET_INT::iterator i;
  cout << "s1.insert(5)" << endl;
  s1.insert(5);
  cout << "s1.insert(10)" << endl;
  s1.insert(10);
  cout << "s1.insert(15)" << endl;
  s1.insert(15);
  cout << "s2.insert(2)" << endl;
  s2.insert(2);
  cout << "s2.insert(4)" << endl;
  s2.insert(4);

  cout << "swap(s1,s2)" << endl;
  swap(s1,s2);

  // Displays: 2,4
  for (i=s1.begin();i!=s1.end();i++)
     cout << "s1 has " << *i << " in its set." << endl;

  // Displays: 5,10,15
  for (i=s2.begin();i!=s2.end();i++)
     cout << "s2 has " << *i << " in its set." << endl;

  cout << "s1.swap(s2)" << endl;
  s1.swap(s2);

  // Displays: 5,10,15
  for (i=s1.begin();i!=s1.end();i++)
     cout << "s1 has " << *i << " in its set." << endl;

  // Displays: 2,4
  for (i=s2.begin();i!=s2.end();i++)
     cout << "s2 has " << *i << " in its set." << endl;
}

Program Output is:

s1.insert(5)
s1.insert(10)
s1.insert(15)
s2.insert(2)
s2.insert(4)
swap(s1,s2)
s1 has 2 in its set.
s1 has 4 in its set.
s2 has 5 in its set.
s2 has 10 in its set.
s2 has 15 in its set.
s1.swap(s2)
s1 has 5 in its set.
s1 has 10 in its set.
s1 has 15 in its set.
s2 has 2 in its set.
s2 has 4 in its set.


sqrt and pow (STL Sample)

The sample code below illustrates how to use the sqrt and pow STL functions in Visual C++.

Required Header:
<valarray>

Prototype:

// sqrt
template<class T>
     inline valarray<T> sqrt(const valarray<T>& x);

// pow
template<class T>
     inline valarray<T> pow(const valarray<T>& x, const valarray<T>& y);

template<class T>
     inline valarray<T> pow(const valarray<T> x, const T& y);

template<class T>
     inline valarray<T> pow(const T& x, const valarray<T>& y);

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
This article illustrates the use of STL sqrt() and pow() functions through sample code. sqrt() returns an object of class valarray<T>, each of whose elements at index I is the square root of x[I]. pow() has three template functions. The first template function returns an object of class valarray<T>, each of whose elements at index I is x[I] raised to the power of y[I]. The second template function stores in element I x[I] raised to the power of y. The third template function stores in element I x raised to the power of y[I].

Sample Code:

//////////////////////////////////////////////////////////////////////
//
// Compile options needed: /GX
//
// main.cpp : Illustrates the use of STL sqrt() and pow() functions.
//
// Functions:
//
//    sqrt, pow
//////////////////////////////////////////////////////////////////////

#include <iostream>                 // for i/o functions
#include <valarray>                 // for valarray
#include <cmath>                    // for sqrt() and pow()

using namespace std ;

#define ARRAY_SIZE  3               // array size

void main()
{
    // Set val_array to contain values 1, 4, 9 for the following test
    valarray<double> val_array(ARRAY_SIZE);

    for (int i = 0; i < ARRAY_SIZE; i++)
        val_array[i] = (i+1) * (i+1);

    // Display the size of val_array
    cout << "Size of val_array = " << val_array.size() << endl;

    // Display the values of val_array before calling sqrt() and pow().
    cout << "The values in val_array:" << endl;
    for (i = 0; i < ARRAY_SIZE; i++)
        cout << val_array[i] << "    ";
    cout << endl << endl;

    // Initialize rev_valarray that is the reverse of val_array.
    valarray<double> rev_valarray(ARRAY_SIZE);
    for (i = 0; i < ARRAY_SIZE; i++)
        rev_valarray[i] = val_array[ARRAY_SIZE - i - 1];

    // Display the size of rev_valarray.
    cout << "Size of rev_valarray = " << rev_valarray.size() << endl;

    // Display the values of rev_valarray.
    cout << "The values in rev_valarray:" << endl;
    for (i = 0; i < ARRAY_SIZE; i++)
        cout << rev_valarray[i] << "    ";
    cout << endl << endl;

    // rvalue_array to hold the return value from calling the sqrt() and
    // pow() functions.
    valarray<double> rvalue_array;

    // ----------------------------------------------------------------
    // sqrt() - display the content of rvalue_array
    // ----------------------------------------------------------------

    // Display the result of val_array after calling sqrt().
    rvalue_array = sqrt(val_array);
    cout << "The result of val_array after calling sqrt():" << endl;
    for (i = 0; i < ARRAY_SIZE; i++)
        cout << rvalue_array[i] << "     ";
    cout << endl << endl;

    // ----------------------------------------------------------------
    // pow() - display the content of rvalue_array
    // ----------------------------------------------------------------

    // This template function returns an object of class valarray<T>,
    // each of whose elements at I is x[I] raised to the power of y[I].
    rvalue_array = pow(val_array, rev_valarray);
    cout << "The result after calling pow(val_array, rev_valarray):"
         << endl;
    for (i = 0; i < ARRAY_SIZE; i++)
        cout << rvalue_array[i] << "     ";
    cout << endl << endl;

    // This template function stores in element I x[I] raised to the
    // power of y, where y=2.0.
    rvalue_array = pow(val_array, 2.0);
    cout << "The result after calling pow(val_array, 2.0):" << endl;
    for (i = 0; i < ARRAY_SIZE; i++)
        cout << rvalue_array[i] << "     ";
    cout << endl << endl;

    // This template function stores in element I x raised to the
    // y[I] power, where x=2.0.
    rvalue_array = pow(2.0, val_array);
    cout << "The result after calling pow(2.0, val_array):" << endl;
    for (i = 0; i < ARRAY_SIZE; i++)
        cout << rvalue_array[i] << "     ";
    cout << endl << endl;
}

Program Output is:

Size of val_array = 3
The values in val_array:
1    4    9

Size of rev_valarray = 3
The values in rev_valarray:
9    4    1

The result of val_array after calling sqrt():
1     2     3

The result after calling pow(val_array, rev_valarray):
1     256     9

The result after calling pow(val_array, 2.0):
1     16     81

The result after calling pow(2.0, val_array):
2     16     512


stack::operator== (STL Sample)

The sample code below illustrates how to use the stack::operator== STL function in Visual C++.

Required Header:
<stack>

Prototype:

template<class _TYPE, class _C, class _A>
     bool stack::bool operator==(const stack<_TYPE, _C, _A>& _X) const;

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
The stack::operator== function returns true if both stacks have equal elements arranged in the same sequence. The stack::operator== function always returns false if the two stacks are of different size.

Sample Code:

//////////////////////////////////////////////////////////////////////
//
// Compile options needed: /GX
//
// StackEqual.cpp :  Illustrates how to use the stack::operator==
//                   function to determine if two stacks are equal.
//
// Functions:
//
//    operator== :  Returns true if both stacks are the same.
//////////////////////////////////////////////////////////////////////

#pragma warning(disable:4786)
#include <stack>
#include <iostream>

using namespace std ;

typedef stack<double> STACK_DOUBLE;

void main()
{
   STACK_DOUBLE stack1,stack2;

   // Add item 4.0 to Stack1.
   cout << "stack1.push(4.0)  s1=[4.0]" << endl;
   stack1.push(4.0);

   // Add item 3.0 to Stack1. Current Stack1 contains items 3.0 (top)
   // 4.0 (bottom).
   cout << "stack1.push(3.0)  s1=[3.0 4.0]" << endl;
   stack1.push(3.0);

   // Add item 4.0 to Stack2.
   cout << "stack2.push(4.0)  s2=[4.0]" << endl;
   stack2.push(4.0);

   // Compare Stack1 and Stack2. Should return False.
   cout << "stack1==stack2 is " <<
      ((stack1==stack2)? "True": "False") << endl << endl;

   // Add item 6.0 to Stack2. Current Stack2 contains items 6.0 (top)
   // 4.0 (bottom)
   cout << "stack2.push(6.0)  s2=[6.0 4.0]" << endl;
   stack2.push(6.0);

   // Compare Stack1 and Stack2. Should return False.
   cout << "stack1==stack2 is " <<
      ((stack1==stack2)? "True": "False") << endl << endl;

   // Keep adding item 8.0 to Stack2. Current Stack2 contains items
   // 8.0 (top), 6.0 and 4.0 (bottom).
   cout << "stack2.push(8.0)  s2=[8.0 6.0 4.0]" << endl;
   stack2.push(8.0);

   // Compare Stack1 and Stack2. Should return False.
   cout << "stack1==stack2 is " <<
      ((stack1==stack2)? "True": "False") << endl << endl;

   // Delete the top item from Stack2. Current Stack2 contains items
   // 6.0 (top) and 4.0 (bottom).
   cout << "stack2.pop()      s2=[6.0 4.0]" << endl;
   stack2.pop();

   // Delete another item from Stack2. Current Stack2 contains item 4.0.
   cout << "stack2.pop()      s2=[4.0]" << endl;
   stack2.pop();

   // Add item 3.0 to Stack2. Current Stack2 contains item 3.0 (top) and
   // 4.0 (bottom).
   cout << "stack2.push(3.0)  s2=[3.0 4.0]" << endl;
   stack2.push(3.0);

   // Compare Stack2 and Stack2. Should return True.
   cout << "stack1==stack2 is " <<
      ((stack1==stack2)? "True": "False") << endl << endl;

   // Delete the top item from Stack2. Current Stack2 contains 4.0.
   cout << "stack2.pop()      s2=[4.0]" << endl;
   stack2.pop();

   // Delete another item from Stack2. Stack2 should be empty.
   cout << "stack2.pop()      s2=[]" << endl;
   stack2.pop();

   // Push item 8.0 to Stack2.
   cout << "stack2.push(8.0)  s2=[8.0]" << endl;
   stack2.push(8.0);

   // Compare Stack1 and Stack2. Should return False.
   cout << "stack1==stack2 is " <<
      ((stack1==stack2)? "True": "False") << endl << endl;
}

Program Output is:

stack1.push(4.0)  s1=[4.0]
stack1.push(3.0)  s1=[3.0 4.0]
stack2.push(4.0)  s2=[4.0]
stack1==stack2 is False

stack2.push(6.0)  s2=[6.0 4.0]
stack1==stack2 is False

stack2.push(8.0)  s2=[8.0 6.0 4.0]
stack1==stack2 is False

stack2.pop()      s2=[6.0 4.0]
stack2.pop()      s2=[4.0]
stack2.push(3.0)  s2=[3.0 4.0]
stack1==stack2 is True

stack2.pop()      s2=[4.0]
stack2.pop()      s2=[]
stack2.push(8.0)  s2=[8.0]
stack1==stack2 is False


stack::operator< (STL Sample)

The sample code below illustrates how to use the stack::operator<< STL function in Visual C++.

Required Header:
<stack>

Prototype:

template<class _TYPE, class _C, class _A>
     bool stack::operator<(const stack<_TYPE, _C, _A>& _X) const;

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
The stack::operator< function returns true if the stack on the left side of the operator is less than the stack on the right side. The following steps are used to determine if one stack is less than another stack: 1. Compare the bottom-most (very first element pushed onto the stack). 2. If the elements are different, the stack with the smaller element is less than the stack with the greater element. Go to Step 5. 3. If the elements are the same and there are more elements, move to the next element in the stack and go back to step 2. 4. If all the elements in the stacks are processed at this point, the stacks are equal. 5. Done.

Sample Code:

//////////////////////////////////////////////////////////////////////
//
// Compile options needed: /GX
//
// StackLessThan.cpp : Illustrates how to use the stack::operator<
//                     function to determine if one stack is less than
//                     another stack.
//
// Functions:
//
//    operator< :  Returns true if the stack is smaller than the stack
//                 passed as the operand.
//////////////////////////////////////////////////////////////////////

#pragma warning(disable:4786)
#include <stack>
#include <iostream>

using namespace std ;

typedef stack<double> STACK_DOUBLE;

void main()
{
   STACK_DOUBLE stack1,stack2;

   // Add item 4.0 to Stack1. Stack1 contains 4.0.
   cout << "stack1.push(4.0)  s1=[4.0]" << endl;
   stack1.push(4.0);

   // Add item 3.0 to Stack1. Stack1 contains 3.0(top) and 4.0(bottom).
   cout << "stack1.push(3.0)  s1=[3.0 4.0]" << endl;
   stack1.push(3.0);

   // Add item 4.0 to Stack2. Stack2 contains 4.0 (top=bottom).
   cout << "stack2.push(4.0)  s2=[4.0]" << endl;
   stack2.push(4.0);

   // Compare if Stack1 is smaller than Stack2. Should return False.
   cout << "stack1<stack2 is " <<
      ((stack1<stack2)? "True": "False") << endl << endl;

   // Add item 6.0 to Stack2. Stack2 contains 6.0(top) and 4.0(bottom).
   cout << "stack2.push(6.0)  s2=[6.0 4.0]" << endl;
   stack2.push(6.0);

   // Compare if Stack1 is smaller than Stack2. Should return True.
   cout << "stack1<stack2 is " <<
      ((stack1<stack2)? "True": "False") << endl << endl;

   // Add item 8.0 to Stack2. Stack2 contains 8.0(top), 6.0 and
   // 4.0(bottom).
   cout << "stack2.push(8.0)  s2=[8.0 6.0 4.0]" << endl;
   stack2.push(8.0);

   // Compare if Stack1 is smaller than Stack2. Should return True.
   cout << "stack1<stack2 is " <<
      ((stack1<stack2)? "True": "False") << endl << endl;

   // Delete item 8.0 from Stack2.
   cout << "stack2.pop()      s2=[6.0 4.0]" << endl;
   stack2.pop();

   // Delete item 6.0 from Stack2.
   cout << "stack2.pop()      s2=[4.0]" << endl;
   stack2.pop();

   // Add item 3.0 to Stack2. Stack2 contains 3.0(top) and 4.0(bottom).
   cout << "stack2.push(3.0)  s2=[3.0 4.0]" << endl;
   stack2.push(3.0);

   // Compare if Stack1 is smaller than Stack2. Should return False.
   cout << "stack1<stack2 is " <<
      ((stack1<stack2)? "True": "False") << endl << endl;

   // Delete item 3.0 from Stack2.
   cout << "stack2.pop()      s2=[4.0]" << endl;
   stack2.pop();

   // Delete item 4.0 from Stack2.
   cout << "stack2.pop()      s2=[]" << endl;
   stack2.pop();

   // Add item 8.0 to Stack2. Stack2 contains 8.0(top=bottom).
   cout << "stack2.push(8.0)  s2=[8.0]" << endl;
   stack2.push(8.0);

   // Compare if Stack1 is smaller than Stack2. Should return True.
   cout << "stack1<stack2 is " <<
      ((stack1<stack2)? "True": "False") << endl << endl;
}

Program Output is:

stack1.push(4.0)  s1=[4.0]
stack1.push(3.0)  s1=[3.0 4.0]
stack2.push(4.0)  s2=[4.0]
stack1<stack2 is False

stack2.push(6.0)  s2=[6.0 4.0]
stack1<stack2 is True

stack2.push(8.0)  s2=[8.0 6.0 4.0]
stack1<stack2 is True

stack2.pop()      s2=[6.0 4.0]
stack2.pop()      s2=[4.0]
stack2.push(3.0)  s2=[3.0 4.0]
stack1<stack2 is False

stack2.pop()      s2=[4.0]
stack2.pop()      s2=[]
stack2.push(8.0)  s2=[8.0]
stack1<stack2 is True


stack::size (STL Sample)

The sample code below illustrates how to use the stack::size STL function in Visual C++.

Required Header:
<stack>

Prototype:

template<class _TYPE, class _C, class _A>
     size_type stack::size() const;

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
The stack::size function returns the number of elements in the stack. It is okay to call this function with an empty stack; it will return a value of 0.

Sample Code:

//////////////////////////////////////////////////////////////////////
//
// Compile options needed: /GX
//
// StackSize.cpp : Illustrates how to use the size function to determine
//                 the number of elements on the stack.
//
// Functions:
//
//    size :  returns the number of elements in the stack.
//////////////////////////////////////////////////////////////////////

#pragma warning(disable:4786)
#include <stack>
#include <string>
#include <iostream>

using namespace std ;

typedef stack<string> STACK_STRING;

void main()
{
   STACK_STRING stack1;

   // Check the size of an empty stack. Should return 0.
   cout << "stack1.size() equals " << stack1.size() << endl;

   // Add item "Hello" to Stack1.
   cout << "stack1.push('Hello')" << endl;
   stack1.push("Hello");

   // Add item "This is the second element" to Stack1.
   cout << "stack1.push('This is the second element')" << endl;
   stack1.push("This is the second element");

   // Check the size of Stack1. Should return 2.
   cout << "stack1.size() equals " << stack1.size() << endl << endl;

   // Add item "Third element" to Stack1.
   cout << "stack1.push('Third element')" << endl;
   stack1.push("Third element");

   // Check the size of Stack1. Should return 3.
   cout << "stack1.size() equals " << stack1.size() << endl << endl;

   // Pop "Third element".
   cout << "stack1.pop()" << endl;
   stack1.pop();

   // Pop "This is the second element".
   cout << "stack1.pop()" << endl;
   stack1.pop();

   // Check the size of Stack1 again. Should return 1.
   cout << "stack1.size() equals " << stack1.size()  << endl << endl;

   // Pop "Hello".
   cout << "stack1.pop()" << endl;
   stack1.pop();

   // Check the size of Stack1. Should return 0.
   cout << "stack1.size() equals " << stack1.size() << endl << endl;
}

Program Output is:

stack1.size() equals 0

stack1.push('Hello')
stack1.push('This is the second element')
stack1.size() equals 2

stack1.push('Third element')
stack1.size() equals 3

stack1.pop()
stack1.pop()
stack1.size() equals 1

stack1.pop()
stack1.size() equals 0


stack::top and stack::empty (STL Sample)

The sample code below illustrates how to use the stack::top and stack::empty STL functions in Visual C++.

Required Header:
<stack>

Prototype:

template<class _TYPE, class _C, class _A>    // Function 1
     value_type& stack::top();

template<class _TYPE, class _C, class _A>    // Function 2
     const value_type& stack::top() const;

template<class _TYPE, class _C, class _A>    // Function 3
     bool stack::empty() const;

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
The top function returns the topmost element of the stack. You should ensure that there are one or more elements on the stack before calling the top function. The first version of the top function returns a reference to the element of the top of the stack, allowing you to modify the value. The second function returns a constant reference, ensuring that you don't accidentally modify the stack. The empty function returns true if there are no elements in the stack. If there are one or more elements, the function will return false. You should use the empty function to verify that there are elements left on the stack before calling the top function.

Sample Code:

//////////////////////////////////////////////////////////////////////
//
// Compile options needed: /GX
//
// StackTop&Empty.cpp : Illustrates how to use the top function to
//                      retrieve the last element of the controlled
//                      sequence. It also illustrates how to use the
//                      empty function to loop though the stack.
// Functions:
//
//    top   :  returns the top element of the stack.
//    empty :  returns true if the stack has 0 elements.
//////////////////////////////////////////////////////////////////////

#pragma warning(disable:4786)
#include <stack>
#include <iostream>

using namespace std ;

typedef stack<int> STACK_INT;

void main()
{
   STACK_INT stack1;

   cout << "stack1.empty() returned " <<
      (stack1.empty()? "true": "false") << endl;  // Function 3

   cout << "stack1.push(2)" << endl;
   stack1.push(2);

   if (!stack1.empty())                           // Function 3
      cout << "stack1.top() returned " <<
      stack1.top() << endl;                       // Function 1

   cout << "stack1.push(5)" << endl;
   stack1.push(5);

   if (!stack1.empty())                           // Function 3
      cout << "stack1.top() returned " <<
      stack1.top() << endl;                       // Function 1

   cout << "stack1.push(11)" << endl;
   stack1.push(11);

   if (!stack1.empty())                           // Function 3
      cout << "stack1.top() returned " <<
      stack1.top() << endl;                       // Function 1

   // Modify the top item. Set it to 6.
   if (!stack1.empty()) {                         // Function 3
      cout << "stack1.top()=6;" << endl;
      stack1.top()=6;                             // Function 1
   }

   // Repeat until stack is empty
   while (!stack1.empty()) {                      // Function 3
      const int& t=stack1.top();                  // Function 2
      cout << "stack1.top() returned " << t << endl;
      cout << "stack1.pop()" << endl;
      stack1.pop();
   }
}

Program Output is:

stack1.empty() returned true
stack1.push(2)
stack1.top() returned 2
stack1.push(5)
stack1.top() returned 5
stack1.push(11)
stack1.top() returned 11
stack1.top()=6;
stack1.top() returned 6
stack1.pop()
stack1.top() returned 5
stack1.pop()
stack1.top() returned 2
stack1.pop()


string::getline (STL Sample)

The sample code below illustrates how to use the string::getline STL function in Visual C++.

Required Header:
<string>

Prototype:

template<class _E, class _TYPE, class _A> inline
     basic_istream<_E, _TYPE>& getline( basic_istream<_E, _TYPE>& Istream,
     basic_string<_E, _TYPE, _A>& Xstring,
     const _E _D=_TYPE::newline());

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
The getline function creates a string containing all of the characters from the input stream until one of the following situations occurs: - End of file. - The delimiter is encountered. - is.max_str() elements have been extracted.

Sample Code:

//////////////////////////////////////////////////////////////////////
//
// Compile options needed: /GX
//
// Getline.cpp : Illustrates how to use the getline function to read a
//               line of text from the keyboard.
//
// Functions:
//
//    getline       Returns a string from the input stream.
//////////////////////////////////////////////////////////////////////

#pragma warning(disable:4786)
#include <string>
#include <iostream>

using namespace std ;

void main()
{
    string s1;
    cout << "Enter a sentence (use <space> as the delimiter):";
    getline(cin,s1, ' ');
    cout << "You entered: " << s1;
}

Program Output is:

Enter a sentence (use <space> as the delimiter): A_space_at_the_end.
You entered: A_space_at_the_end.


string::operator== (STL Sample)

The sample code below illustrates how to use the string::operator== STL function in Visual C++.

Required Header:
<string>

Prototype:

Function 1:
template<class _E, class _TYPE, class _A> inline
     bool operator==(const basic_string<_E, _TYPE, _A>& LString,
     const _E *RCharArray);

Function 2:
template<class _E, class _TYPE, class _A> inline
     bool operator==(const _E * LCharArray,
     const basic_string<_E, _TYPE, _A>& RString);

Function 3:
template<class _E, class _TYPE, class _A> inline
     bool operator==(const basic_string<_E, _TYPE, _A>& LString,
     const basic_string<_E, _TYPE, _A>& RString);

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
There are three versions of the string::operator== function. The first two functions compare a null-terminated character array against a basic_string. They perform this operation by using the basic_string's string::compare function and returning true if the compare function returns a 0 value. The third function compares two basic_string variables, using the string::compare function of the first basic_string variable. For more information on the compare function, see the string::compare function. Note that this operator does not work with NULL pointer for the character array. You will need to make sure that the character array is not NULL before you pass it to the operator.

Sample Code:

//////////////////////////////////////////////////////////////////////
//
// Compile options needed: /GX
//
// StringEqual.cpp: Illustrates how to use the operator== to test for
//                  equality of a basic_string variable and a
//                  null-terminated string. It also illustrates how to
//                  use the operator== to test for equality of two
//                  basic_string variables.
//
// Functions:
//
//    operator==   returns true if the basic_string and the null-
//                 terminated string are equal.
//    operator==   returns true if both basic_strings are equal.
//////////////////////////////////////////////////////////////////////

#pragma warning(disable:4786)
#include <string>
#include <iostream>

using namespace std ;

void trueFalse(int x)
{
  cout << (x? "True": "False") << endl;
}

void main()
{
   string S1="ABC";
   string S2="ABC";
   string S3="DEF";
   string S4; //This specifies an empty initial-controlled sequence.
   char CP1[]="abc";
   char CP2[]="DEF";
   char *CP3 = NULL;

   cout << "S1 is " << S1 << endl;
   cout << "S2 is " << S2 << endl;
   cout << "S3 is " << S3 << endl;
   cout << "S4 is " << S4 << endl;
   cout << "CP1 is " << CP1 << endl;
   cout << "CP2 is " << CP2 << endl;

   cout << "S1==CP1 returned ";
   trueFalse(S1==CP1);  // False    (calls function 1)

   cout << "S1==CP2 returned ";
   trueFalse(S1==CP2);  // False   (calls function 1)

   cout << "CP1==S1 returned ";
   trueFalse(CP1==S1);  // False    (calls function 2)

   cout << "CP2==S1 returned ";
   trueFalse(CP2==S1);  // False   (calls function 2)

   cout << "S1==S2 returned ";
   trueFalse(S1==S2);   // True    (calls function 3)

   cout << "S1==S3 returned ";
   trueFalse(S1==S3);   // False   (calls function 3)

   cout << "S1==S4 returned ";
   trueFalse(S1==S4);   // False   (calls function 3)

   // Following use of the operator will cause the program to
   // crash since CP3 is NULL.
   // cout << "S1==CP3 returned ";
   // trueFalse(S1==CP3);
}

Program Output is:

S1 is ABC
S2 is ABC
S3 is DEF
S4 is
CP1 is abc
CP2 is DEF
S1==CP1 returned False
S1==CP2 returned False
CP1==S1 returned False
CP2==S1 returned False
S1==S2 returned True
S1==S3 returned False
S1==S4 returned False


string::operator> (STL Sample)

The sample code below illustrates how to use the string::operator> STL function in Visual C++.

Required Header:
<string>

Prototype:

Function 1:
template<class _E, class _TYPE, class _A> inline
     bool operator>(const basic_string<_E, _TYPE, _A>& LString,
     const _E *RCharArray);

Function 2:
template<class _E, class _TYPE, class _A> inline
     bool operator>(const _E *LCharArray,
     const basic_string<_E, _TYPE, _A>& RString);

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
There are two versions of the string::operator> function. Both versions are used to compare a null-terminated character array to a basic_string. They perform this operation by returning the result of (RString<LCharArray or RCharArray<LString). For more information on this comparison, see the string::operator< function. Note that this operator does not work with NULL pointer for the character array. You will need to make sure that the character array is not NULL before you pass it to the operator.

Sample Code:

//////////////////////////////////////////////////////////////////////
//
// Compile options needed: /GX
//
// StringGreaterThan.cpp : Illustrates how to use the operator> to
//                         compare a basic_string variable to a
//                         null-terminated string.
//
// Functions:
//
//    operator>    Returns true if the second parameter is less than
//                 the first.
//////////////////////////////////////////////////////////////////////

#pragma warning(disable:4786)
#include <string>
#include <iostream>

using namespace std ;

void trueFalse(int x)
{
  cout << (x? "True": "False") << endl;
}

void main()
{
   string S1="ABC";
   char CP1[]="ABC";
   char CP2[]="DEF";
   char CP3[]="ABCD";
   char CP4[]="abc";

   cout << "S1 is " << S1 << endl;
   cout << "CP1 is " << CP1 << endl;
   cout << "CP2 is " << CP2 << endl;
   cout << "CP3 is " << CP3 << endl;
   cout << "CP4 is " << CP4 << endl;

   cout << "S1>CP1 returned ";
   trueFalse(S1>CP1);  // False  (calls function 1)

   cout << "S1>CP2 returned ";
   trueFalse(S1>CP2);  // False  (calls function 1)

   cout << "S1>CP4 returned ";
   trueFalse(S1>CP4);  // False   (calls function 1)

   cout << "CP1>S1 returned ";
   trueFalse(CP1>S1);  // False  (calls function 2)

   cout << "CP2>S1 returned ";
   trueFalse(CP2>S1);  // True   (calls function 2)

   cout << "CP3>S1 returned ";
   trueFalse(CP3>S1);  // True   (calls function 2)
}

Program Output is:

S1 is ABC
CP1 is ABC
CP2 is DEF
CP3 is ABCD
CP4 is abc
S1>CP1 returned False
S1>CP2 returned False
S1>CP4 returned False
CP1>S1 returned False
CP2>S1 returned True
CP3>S1 returned True


string::operator>= (STL Sample)

The sample code below illustrates how to use the string::operator>= STL function in Visual C++.

Required Header:
<string>

Prototype:

Function 1:
template<class _E, class _TYPE, class _A> inline
     bool operator>=(const basic_string<_E, _TYPE, _A>& _L,
     const _E *_R);

Function 2:
template<class _E, class _TYPE, class _A> inline
    bool operator>=(const _E * _L,
    const basic_string<_E, _TYPE, _A>& _R);

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
There are two versions of the string::operator>= function. Both versions are used to compare a null-terminated character array against a basic_string. They perform this operation by negating the result of (_L < _R). For more information on this comparison, please see the string::operator< function.

Sample Code:

//////////////////////////////////////////////////////////////////////
//
// Compile options needed: none
//
// StringGreaterEqual.cpp:
//     Illustrates how to use the operator>= to compare a
//     basic_string variable and a null-terminated string.
//
// Functions:
//
//     operator>=   Returns true if the first parameter is not less than
//                  the second.
//
// Written by Derek Jamison
// of Microsoft AnswerPoint Support,
// Copyright (c) 1996 Microsoft Corporation. All rights reserved.
//////////////////////////////////////////////////////////////////////

#pragma warning(disable:4786)
#include <string>
#include <iostream>

using namespace std ;

void truefalse(int x)
{
  cout << (x?"True":"False") << endl;
}

void main()
{
   string S1="ABC";
   char CP1[4]="ABC";
   char CP2[4]="DEF";

   cout << "S1 is " << S1 << endl;
   cout << "CP1 is " << CP1 << endl;
   cout << "CP2 is " << CP2 << endl;

   cout << "S1>=CP1 returned ";
   truefalse(S1>=CP1);  // True   (calls function 1)

   cout << "S1>=CP2 returned ";
   truefalse(S1>=CP2);  // False  (calls function 1)

   cout << "CP1>=S1 returned ";
   truefalse(CP1>=S1);  // True   (calls function 2)

   cout << "CP2>=S1 returned ";
   truefalse(CP2>=S1);  // True   (calls function 2)
}

Program Output is:

S1 is ABC
CP1 is ABC
CP2 is DEF
S1>=CP1 returned True
S1>=CP2 returned False
CP1>=S1 returned True
CP2>=S1 returned True


string::operator>> (STL Sample)

The sample code below illustrates how to use the string::operator>> STL function in Visual C++.

Required Header:
<string>

Prototype:

template<class E, class TYPE, class A> inline
     basic_istream<E, TYPE>&
     operator>>(basic_istream<E, TYPE>& InStream,
     basic_string<E, TYPE, A>& String);

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
The operator>> is used to populate a string with the contents of an input stream.

Sample Code:

//////////////////////////////////////////////////////////////////////
//
// Compile options needed: /GX
//
// StringExtract.cpp : Illustrates how to use the operator>> to extract
//                     a string from an input stream, populating a string
//                     variable with the contents.
//
// Functions:
//
//    operator>>  Extracts a string from an input stream.
//////////////////////////////////////////////////////////////////////

#pragma warning(disable:4786)
#include <string>
#include <iostream>

using namespace std ;

void main()
{
    string s1;
    cout << "Enter a word: ";
    cin >> s1;
    cout << endl << "You entered: " << s1;
}

Program Output is:

Enter a word: Sample

You entered: Sample


string::operator< (STL Sample)

The sample code below illustrates how to use the string::operator< STL function in Visual C++.

Required Header:
<string>

Prototype:

Function 1:
template<class _E, class _TYPE, class _A> inline
     bool operator<(const basic_string<_E, _TYPE, _A>& LString,
     const _E *RCharArray);

Function 2:
template<class _E, class _TYPE, class _A> inline
     bool operator<(const _E *LCharArray,
     const basic_string<_E, _TYPE, _A>& RString);

Function 3:
template<class _E, class _TYPE, class _A> inline
     bool operator<(const basic_string<_E, _TYPE, _A>& LString,
     const basic_string<_E, _TYPE, _A>& RString);

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
There are three versions of the string::operator< function. Two of the functions compare a null-terminated character array against a basic_string. They perform this operation by using the basic_string's string::compare function and returning a value based on the results of the compare function. The third function compares two basic_string variables, using the string::compare function of the first basic_string variable. For more information on the compare function, please see the string::compare function. Note that this operator does not work with NULL pointer for the character array. You will need to make sure that the character array is not NULL before you pass it to the operator.

Sample Code:

//////////////////////////////////////////////////////////////////////
//
// Compile options needed: /GX
//
// StringLessThan.cpp : Illustrates how to use the operator< to compare
//                      a basic_string variable and a null-terminated
//                      string. It also illustrates how to use the
//                      operator< to compare two basic_string variables.
//
// Functions:
//
//    operator<    Returns true if the first parameter is less than the
//                 second.
//////////////////////////////////////////////////////////////////////

#pragma warning(disable:4786)
#include <string>
#include <iostream>

using namespace std ;

void trueFalse(int x)
{
  cout << (x? "True": "False") << endl;
}

void main()
{
   string S1="ABC";
   string S2="ABC";
   string S3="DEF";
   string S4="abc";
   char CP1[]="ABC";
   char CP2[]="DEF";
   char CP3[]="ABCD";

   cout << "S1 is " << S1 << endl;
   cout << "S2 is " << S2 << endl;
   cout << "S3 is " << S3 << endl;
   cout << "S4 is " << S4 << endl;
   cout << "CP1 is " << CP1 << endl;
   cout << "CP2 is " << CP2 << endl;
   cout << "CP3 is " << CP3 << endl;

   cout << "S1<CP1 returned ";
   trueFalse(S1<CP1);  // False    (calls function 1)

   cout << "S1<CP2 returned ";
   trueFalse(S1<CP2);  // True   (calls function 1)

   cout << "CP1<S1 returned ";
   trueFalse(CP1<S1);  // False    (calls function 2)

   cout << "CP2<S1 returned ";
   trueFalse(CP2<S1);  // False    (calls function 2)

   cout << "S1<S2 returned ";
   trueFalse(S1<S2);   // False    (calls function 3)

   cout << "S1<S3 returned ";
   trueFalse(S1<S3);   // True   (calls function 3)

   cout << "S1<S4 returned ";
   trueFalse(S1<S4);   // True   (calls function 3)

   cout << "S1<CP3 returned ";
   trueFalse(S1<CP3);  // True   (calls function 1)
}

Program Output is:

S1 is ABC
S2 is ABC
S3 is DEF
S4 is abc
CP1 is ABC
CP2 is DEF
CP3 is ABCD
S1<CP1 returned False
S1<CP2 returned True
CP1<S1 returned False
CP2<S1 returned False
S1<S2 returned False
S1<S3 returned True
S1<S4 returned True
S1<CP3 returned True


string::operator<= (STL Sample)

The sample code below illustrates how to use the string::operator<= STL function in Visual C++.

Required Header:
<string>

Prototype:

Function 1:
template<class _E, class _TYPE, class _A> inline
     bool operator<=(const basic_string<_E, _TYPE, _A>& LString,
     const _E *RCharArray);

Function 2:
template<class _E, class _TYPE, class _A> inline
     bool operator<=(const _E * LCharArray,
     const basic_string<_E, _TYPE, _A>& RString);

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
There are two versions of the string::operator<= function. Both versions are used to compare a null-terminated character array to a basic_string. They perform this operation by negating the result of (RString<LCharArray or RCharArray<LString). For more information on this comparison, please see the string::operator< function. Note that this operator does not work with NULL pointer for the character array. You will need to make sure that the character array is not NULL before you pass it to the operator.

Sample Code:

/////////////////////////////////////////////////////////////////////////
//
// Compile options needed: /GX
//
// StringLessEqual.cpp : Illustrates how to use the operator<= to compare
//                       a basic_string variable to a null-terminated
//                       string.
//
// Functions:
//
//    operator<=   Returns true if the second parameter is not less
//                 than the first.
/////////////////////////////////////////////////////////////////////////

#pragma warning(disable:4786)
#include <string>
#include <iostream>

using namespace std ;

void trueFalse(int x)
{
  cout << (x? "True": "False") << endl;
}

void main()
{
   string S1="DEF";
   char CP1[]="ABC";
   char CP2[]="DEF";
   char CP3[]="DEFG";
   char CP4[]="def";

   cout << "S1 is " << S1 << endl;
   cout << "CP1 is " << CP1 << endl;
   cout << "CP2 is " << CP2 << endl;
   cout << "CP3 is " << CP3 << endl;
   cout << "CP4 is " << CP4 << endl;

   cout << "S1<=CP1 returned ";
   trueFalse(S1<=CP1);  // False  (calls function 1)

   cout << "S1<=CP2 returned ";
   trueFalse(S1<=CP2);  // True   (calls function 1)

   cout << "S1<=CP3 returned ";
   trueFalse(S1<=CP3);  // True   (calls function 1)

   cout << "CP1<=S1 returned ";
   trueFalse(CP1<=S1);  // True   (calls function 2)

   cout << "CP2<=S1 returned ";
   trueFalse(CP2<=S1);  // True   (calls function 2)

   cout << "CP4<=S1 returned ";
   trueFalse(CP4<=S1);  // False   (calls function 2)
}

Program Output is:

S1 is DEF
CP1 is ABC
CP2 is DEF
CP3 is DEFG
CP4 is def
S1<=CP1 returned False
S1<=CP2 returned True
S1<=CP3 returned True
CP1<=S1 returned True
CP2<=S1 returned True
CP4<=S1 returned False


string::operator<< (STL Sample)

The sample code below illustrates how to use the string::operator<< STL function in Visual C++.

Required Header:
<string>

Prototype:

   template<class _E, class _TYPE, class _A> inline
   basic_ostream<_E, _TYPE>&
   operator<<( basic_ostream<_E, _TYPE>& OStream,
               const basic_string<_E, _TYPE, _A>& XString);

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
The operator<< is used to insert a string into an output stream.

Sample Code:

//////////////////////////////////////////////////////////////////////
//
// Compile options needed: /GX
//
// StringInsertion.cpp : Illustrates how to use the insertion operator
//                       (operator<<) to insert a string into an output
//                       stream.
//
// Functions:
//
//    operator<<   Inserts a string into an output stream.
//////////////////////////////////////////////////////////////////////

#pragma warning(disable:4786)
#include <string>
#include <iostream>

using namespace std ;

void main()
{
    string msg="Hello!  This is the insertion operator.";
    cout << msg << endl;
}

Program Output is:

Hello!  This is the insertion operator.


string::operator+ (STL Sample)

The sample code below illustrates how to use the string::operator+ STL function in Visual C++.

Required Header:
<string>

Prototype:

Function 1:
template<class _E, class _TYPE, class _A> inline
     basic_string<_E, _TYPE, _A>
     operator+(const basic_string<_E, _TYPE, _A>& LString,
     const _E *RCharArray);

Function 2:
template<class _E, class _TYPE, class _A> inline
     basic_string<_E, _TYPE, _A>
     operator+(const _E *LCharArray,
     const basic_string<_E, _TYPE, _A>& RString);

Function 3:
template<class _E, class _TYPE, class _A> inline
     basic_string<_E, _TYPE, _A>
     operator+(const basic_string<_E, _TYPE, _A>& LString,
     const _E RChar);

Function 4:
template<class _E, class _TYPE, class _A> inline
     basic_string<_E, _TYPE, _A>
     operator+(const _E LChar,
     const basic_string<_E, _TYPE, _A>& RString);

Function 5:
template<class _E, class _TYPE, class _A> inline
     basic_string<_E, _TYPE, _A>
     operator+(const basic_string<_E, _TYPE, _A>& LString,
     const basic_string<_E, _TYPE, _A>& RString);

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
There are five versions of the string::operator+ function. Two functions are used to concatenate a null-terminated character array and a basic_string. Two functions are used to concatenate a character and a basic_string. The last function is used to concatenate two basic_string variables.

Sample Code:

//////////////////////////////////////////////////////////////////////
//
// Compile options needed: /GX
//
// StringPlus.cpp : Illustrates how to use the operator+ to concatenate
//                  a null-terminated character array and a basic_string,
//                  how to concatenate a character and a basic_string,
//                  and how to concatenate two basic_string variables.
//
// Functions:
//
//    operator+ : Concatenates a null-terminated character array and
//                a basic_string.
//    operator+ : Concatenates a character array and a basic_string.
//    operator+ : Concatenates two basic_string variables.
//////////////////////////////////////////////////////////////////////

#pragma warning(disable:4786)
#include <string>
#include <iostream>

using namespace std ;

void main()
{
   string result;
   string S1="ABC";
   string S2="DEF";
   char CP1[]="GHI";
   char C='J';

   cout << "S1 is " << S1 << endl;
   cout << "S2 is " << S2 << endl;
   cout << "CP1 is " << CP1 << endl;
   cout << "C is " << C << endl;

   result=S1+CP1;                           // Function 1  (ABCGHI)
   cout << "S1+CP1 is " << result << endl;

   result=CP1+S1;                           // Function 2  (GHIABC)
   cout << "CP1+S1 is " << result << endl;

   result=S1+S2;                            // Function 3  (ABCDEF)
   cout << "S1+S2 is " << result << endl;

   result=S1+C;                             // Function 4  (ABCJ)
   cout << "S1+C is " << result << endl;

   result=C+S1;                             // Function 5  (JABC)
   cout << "C+S1 is " << result << endl;
}

Program Output is:

S1 is ABC
S2 is DEF
CP1 is GHI
C is J
S1+CP1 is ABCGHI
CP1+S1 is GHIABC
S1+S2 is ABCDEF
S1+C is ABCJ
C+S1 is JABC


string::operator!= (STL Sample)

The sample code below illustrates how to use the string::operator!= STL function in Visual C++.

Required Header:
<string>

Prototype:

Function 1:
template<class _E, class _TYPE, class _A> inline
     bool operator!=(const basic_string<_E, _TYPE, _A>& LString,
     const _E *RCharArray);

Function 2:
template<class _E, class _TYPE, class _A> inline
     bool operator!=(const _E *LCharArray,
     const basic_string<_E, _TYPE, _A>& RString);

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
There are two versions of the string::operator!= function. Both versions are used to compare a null-terminated character array against a basic_string. They perform this operation by negating the result of (LString==RCharArray) or (LCharArray==RString). For more information on this comparison, please see the string::operator== function. Notice that this operator does not work with NULL pointer for the character array. You will need to make sure that the character array is not NULL before you pass it to the operator.

Sample Code:

//////////////////////////////////////////////////////////////////////
//
// Compile options needed: /GX
//
// StringNotEqual.cpp : Illustrates how to use the operator!= to test for
//                      non-equality of a basic_string variable and a
//                      null-terminated string.
//
// Functions:
//
//    operator!=   Returns true if the basic_string and the null-
//                 terminated string are not equal.
//////////////////////////////////////////////////////////////////////

#pragma warning(disable:4786)
#include <string>
#include <iostream>

using namespace std ;

void trueFalse(int x)
{
  cout << (x? "True": "False") << endl;
}

void main()
{
   string S1="ABC";
   char CP1[]="ABC";
   char CP2[]="DEF";
   char CP3[]="abc";

   cout << "S1 is " << S1 << endl;
   cout << "CP1 is " << CP1 << endl;
   cout << "CP2 is " << CP2 << endl;
   cout << "CP3 is " << CP3 << endl;

   cout << "S1!=CP1 returned ";
   trueFalse(S1!=CP1);  // False  (calls function 1)

   cout << "S1!=CP2 returned ";
   trueFalse(S1!=CP2);  // True   (calls function 1)

   cout << "S1!=CP3 returned ";
   trueFalse(S1!=CP3);  // True   (calls function 1)

   cout << "CP1!=S1 returned ";
   trueFalse(CP1!=S1);  // False  (calls function 2)

   cout << "CP2!=S1 returned ";
   trueFalse(CP2!=S1);  // True   (calls function 2)

   cout << "CP3!=S1 returned ";
   trueFalse(CP3!=S1);  // True   (calls function 2)
}

Program Output is:

S1 is ABC
CP1 is ABC
CP2 is DEF
CP3 is abc
S1!=CP1 returned False
S1!=CP2 returned True
S1!=CP3 returned True
CP1!=S1 returned False
CP2!=S1 returned True
CP3!=S1 returned True


Trigonometry Functions (Sample)

The sample code below illustrates how to use trigonometry (sin, cos, tan, and so on) functions in Visual C++.

Required Header:
<valarray>

Prototype:

// acos
template<class T>
     inline valarray<T> acos(const valarray<T>& x);

// asin
template<class T>
     inline valarray<T> asin(const valarray<T>& x);

// atan
template<class T>
     inline valarray<T> atan(const valarray<T>& x);

// atan2
template<class T>
     inline valarray<T> atan2(const valarray<T>& x, const valarray<T>& y);

template<class T>
     inline valarray<T> atan2(const valarray<T> x, const T& y);

template<class T>
     inline valarray<T> atan2(const T& x, const valarray<T>& y);

// cos
template<class T>
     inline valarray<T> cos(const valarray<T>& x);

// cosh
template<class T>
     inline valarray<T> cosh(const valarray<T>& x);

// sin
template<class T>
     inline valarray<T> sin(const valarray<T>& x);

// sinh
template<class T>
     inline valarray<T> sinh(const valarray<T>& x);

// tan
template<class T>
     inline valarray<T> tan(const valarray<T>& x);

// tanh
template<class T>
     inline valarray<T> tanh(const valarray<T>& x);

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
This article illustrates the use of STL trigonometry functions through sample code.

Sample Code:

//////////////////////////////////////////////////////////////////////
//
// Compile options needed: /GX
//
// main.cpp : Illustrates the use of STL trigonometry functions.
//
// Functions:
//
//  acos, asin, atan, atan2, cos, cosh, sin, sinh, tan, tanh
//////////////////////////////////////////////////////////////////////

#include <iostream>                 // for i/o functions
#include <valarray>                 // for valarray
#include <cmath>                    // for trigonometry functions

using namespace std ;

#define ARRAY_SIZE  3               // array size

void main()
{
    // Initialize val_array to values -1, 0 and 1.
    valarray<double> val_array(ARRAY_SIZE);
    for (int i = 0; i < ARRAY_SIZE; i++)
        val_array[i] = i - 1;

    // Display the size of val_array.
    cout << "Size of val_array = " << val_array.size() << endl;

    // Display the values of val_array before calling any trigonometry
    // functions.
    cout << "The values in val_array:" << endl;
    for (i = 0; i < ARRAY_SIZE; i++)
        cout << val_array[i] << "    ";
    cout << endl << endl;

    // Initialize rev_valarray that is the reverse of val_array.
    valarray<double> rev_valarray(ARRAY_SIZE);
    for (i = 0; i < ARRAY_SIZE; i++)
        rev_valarray[i] = val_array[ARRAY_SIZE - i - 1];

    // Display the size of rev_valarray.
    cout << "Size of rev_valarray = " << rev_valarray.size() << endl;

    // Display the values of rev_valarray.
    cout << "The values in rev_valarray:" << endl;
    for (i = 0; i < ARRAY_SIZE; i++)
        cout << rev_valarray[i] << "    ";
    cout << endl << endl;

    // rvalue_array to hold the return value from calling the trigonometry
    // functions.
    valarray<double> rvalue_array;

    // ----------------------------------------------------------------
    // acos() - display the result of rvalue_array
    // ----------------------------------------------------------------
    rvalue_array = acos(val_array);
    cout << "The result after calling acos():" << endl;
    for (i = 0; i < ARRAY_SIZE; i++)
        cout << rvalue_array[i] << "     ";
    cout << endl << endl;

    // ----------------------------------------------------------------
    // asin() - display the result of rvalue_array
    // ----------------------------------------------------------------
    rvalue_array = asin(val_array);
    cout << "The result after calling asin():" << endl;
    for (i = 0; i < ARRAY_SIZE; i++)
        cout << rvalue_array[i] << "     ";
    cout << endl << endl;

    // ----------------------------------------------------------------
    // atan() - display the result of rvalue_array
    // ----------------------------------------------------------------
    rvalue_array = atan(val_array);
    cout << "The result after calling atan():" << endl;
    for (i = 0; i < ARRAY_SIZE; i++)
        cout << rvalue_array[i] << "     ";
    cout << endl << endl;

    // ----------------------------------------------------------------
    // atan2() - display the result of rvalue_array
    // ----------------------------------------------------------------

    // This template function returns an object of class valarray<T>,
    // each of whose elements at I is the arctangent of x[I] / y[I].
    rvalue_array = atan2(val_array, rev_valarray);
    cout << "The result after calling atan2(val_array, rev_valarray):"
         << endl;
    for (i = 0; i < ARRAY_SIZE; i++)
        cout << rvalue_array[i] << "     ";
    cout << endl << endl;

    // This template function stores in element I the arctangent of
    // x[I] / y.
    rvalue_array = atan2(val_array, 3.1416);
    cout << "The result after calling atan2(val_array, 3.1416):" << endl;
    for (i = 0; i < ARRAY_SIZE; i++)
        cout << rvalue_array[i] << "     ";
    cout << endl << endl;

    // This template function stores in element I the arctangent of
    // x / y[I].
    rvalue_array = atan2(3.1416, val_array);
    cout << "The result after calling atan2(3.1416, val_array):" << endl;
    for (i = 0; i < ARRAY_SIZE; i++)
        cout << rvalue_array[i] << "     ";
    cout << endl << endl;

    // ----------------------------------------------------------------
    // cos() - display the result of rvalue_array
    // ----------------------------------------------------------------
    rvalue_array = cos(val_array);
    cout << "The result after calling cos():" << endl;
    for (i = 0; i < ARRAY_SIZE; i++)
        cout << rvalue_array[i] << "     ";
    cout << endl << endl;

    // ----------------------------------------------------------------
    // cosh() - display the result of rvalue_array
    // ----------------------------------------------------------------
    rvalue_array = cosh(val_array);
    cout << "The result after calling cosh():" << endl;
    for (i = 0; i < ARRAY_SIZE; i++)
        cout << rvalue_array[i] << "     ";
    cout << endl << endl;

    // ----------------------------------------------------------------
    // sin() - display the result of val_array
    // ----------------------------------------------------------------
    rvalue_array = sin(val_array);
    cout << "The result after calling sin():" << endl;
    for (i = 0; i < ARRAY_SIZE; i++)
        cout << rvalue_array[i] << "     ";
    cout << endl << endl;

    // ----------------------------------------------------------------
    // sinh() - display the result of val_array
    // ----------------------------------------------------------------
    rvalue_array = sinh(val_array);
    cout << "The result after calling sinh():" << endl;
    for (i = 0; i < ARRAY_SIZE; i++)
        cout << rvalue_array[i] << "     ";
    cout << endl << endl;

    // ----------------------------------------------------------------
    // tan() - display the result of val_array
    // ----------------------------------------------------------------
    rvalue_array = tan(val_array);
    cout << "The result after calling tan():" << endl;
    for (i = 0; i < ARRAY_SIZE; i++)
        cout << rvalue_array[i] << "     ";
    cout << endl << endl;

    // ----------------------------------------------------------------
    // tanh() - display the result of val_array
    // ----------------------------------------------------------------
    rvalue_array = tanh(val_array);
    cout << "The result after calling tanh():" << endl;
    for (i = 0; i < ARRAY_SIZE; i++)
        cout << rvalue_array[i] << "     ";
    cout << endl << endl;
}

Program Output is:

Size of val_array = 3
The values in val_array:
-1    0    1

Size of rev_valarray = 3
The values in rev_valarray:
1    0    -1

The result after calling acos():
3.14159     1.5708     0

The result after calling asin():
-1.5708     0     1.5708

The result after calling atan():
-0.785398     0     0.785398

The result after calling atan2(val_array, rev_valarray):
-0.785398     0     2.35619

The result after calling atan2(val_array, 3.1416):
-0.308168     0     0.308168

The result after calling atan2(3.1416, val_array):
1.87896     1.5708     1.26263

The result after calling cos():
0.540302     1     0.540302

The result after calling cosh():
1.54308     1     1.54308

The result after calling sin():
-0.841471     0     0.841471

The result after calling sinh():
-1.1752     0     1.1752

The result after calling tan():
-1.55741     0     1.55741

The result after calling tanh():
-0.761594     0     0.761594


unary_function<> Structure (STL Sample)

The sample code below illustrates how to use the unary_function<> structure in Visual C++.

Required Header:
< functional >

Prototype:

template<class _A, class _R>
     struct unary_function
     {
         typedef _A argument_type;
         typedef _R result_type;
     };

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
unary_function is used as a base class to better define operator functions in the following format: result_type classname::operatorX(argument_type).

Sample Code:

////////////////////////////////////////////
//
// Compile options needed: none
//
// Structure used:
//       unary_function<int, float> - allows us
//       to write operator functions accepting an
//       integer and returning floats.
////////////////////////////////////////////

#include <functional>
#include <iostream>

using namespace std ;

/* derive class from unary_function in order to use it */

class unary_test : public unary_function<int,float>
{
public:
  float value;
  unary_test(){value=10.0;}
  unary_test(float x){value=x;}
  result_type operator*(argument_type x);
  result_type operator-(argument_type x);
};

/* You can now easily create operators that accept */
/* an int and return a float.                     */

unary_test::result_type unary_test::operator*(unary_test::argument_type x)
{
  value*=x;
  cout << "New value after * is " << value << endl ;
  return value;
}

unary_test::result_type unary_test::operator-(unary_test::argument_type x)
{
  value-+(float)x;
  cout << "New value after minus is " << value << endl ;

  return value;
}

void main(void)
{
  unary_test item;
  unary_test item2(18.0);

  cout << "Begin" << endl ;
  cout.setf(ios::fixed) ;
  item = item * 2;
  item2 = item2 - 5;
}

Program Output is:

Begin
New value after * is 20.000000
New value after minus is 18.000000


upper_bound (STL Sample)

The sample code below illustrates how to use the upper_bound STL function in Visual C++.

Required Header:
<algorithm>

Prototype:

template<class ForwardIterator, class T>
     inline ForwardIterator upper_bound(ForwardIterator first, ForwardIterator last, const T& value)

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
The upper_bound algorithm returns the last location in the sequence that value can be inserted such that the order of the sequence is maintained. upper_bound returns an iterator positioned at the location that value can be inserted in the range [first..last), or returns last if no such position exists. upper_bound assumes the range [first ..last) is sorted using operator<.

Sample Code:

//////////////////////////////////////////////////////////////////////
//
// Compile options needed: /GX
//
// upper_bound.cpp : Illustrates how to use the upper_bound
//                   function.
//
// Functions:
//
//    upper_bound : Return the upper bound within a range.
//////////////////////////////////////////////////////////////////////

// disable warning C4786: symbol greater than 255 character,
// okay to ignore
#pragma warning(disable: 4786)

#include <iostream>
#include <algorithm>
#include <functional>
#include <vector>

using namespace std;

void main()
{
    const int VECTOR_SIZE = 8 ;

    // Define a template class vector of int
    typedef vector<int > IntVector ;

    //Define an iterator for template class vector of strings
    typedef IntVector::iterator IntVectorIt ;

    IntVector Numbers(VECTOR_SIZE) ;

    IntVectorIt start, end, it, location ;

    // Initialize vector Numbers
    Numbers[0] = 4 ;
    Numbers[1] = 10;
    Numbers[2] = 10 ;
    Numbers[3] = 30 ;
    Numbers[4] = 69 ;
    Numbers[5] = 70 ;
    Numbers[6] = 96 ;
    Numbers[7] = 100;

    start = Numbers.begin() ;   // location of first
                                // element of Numbers

    end = Numbers.end() ;       // one past the location
                                // last element of Numbers

    // print content of Numbers
    cout << "Numbers { " ;
    for(it = start; it != end; it++)
        cout << *it << " " ;
    cout << " }\n" << endl ;

    //return the last location at which 10 can be inserted
    // in Numbers
    location = upper_bound(start, end, 10) ;

    cout << "Element 10 can be inserted at index "
        << location - start << endl ;
}

Program Output is:

Numbers { 4 10 10 30 69 70 96 100  }

Element 10 can be inserted at index 3


Predicate Version of upper_bound (STL Sample)

The sample code below illustrates how to use the predicate version of the upper_bound STL function in Visual C++.

Required Header:
<algorithm>

Prototype:

template<class ForwardIterator, class T, class Compare>
     inline orwardIterator upper_bound(ForwardIterator first, ForwardIterator last,
     const T& value, Compare compare)

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
The upper_bound algorithm returns the last location in the sequence that value can be inserted such that the order of the sequence [first..last) is maintained. upper_bound returns an iterator positioned at the location that value can be inserted in the range [first..last), or returns last if no such position exists. This version assumes the range [first..last) is sorted sequentially using the compare function.

Sample Code:

//////////////////////////////////////////////////////////////////////
//
// Compile options needed: /GX
//
// upper_bound.cpp : Illustrates how to use the predicate version
//                   of the upper_bound function.
//
// Functions:
//
//    upper_bound : Return the upper bound within a range.

//////////////////////////////////////////////////////////////////////

// disable warning C4786: symbol greater than 255 character,
// okay to ignore
#pragma warning(disable: 4786)

#include <iostream>
#include <algorithm>
#include <functional>
#include <vector>

using namespace std;

void main()
{
    const int VECTOR_SIZE = 8 ;

    // Define a template class vector of int
    typedef vector<int > IntVector ;

    //Define an iterator for template class vector of strings
    typedef IntVector::iterator IntVectorIt ;

    IntVector Numbers(VECTOR_SIZE) ;

    IntVectorIt start, end, it, location ;

    // Initialize vector Numbers
    Numbers[0] = 4 ;
    Numbers[1] = 10;
    Numbers[2] = 70 ;
    Numbers[3] = 10 ;
    Numbers[4] = 30 ;
    Numbers[5] = 69 ;
    Numbers[6] = 96 ;
    Numbers[7] = 100;

    start = Numbers.begin() ;   // location of first
                                // element of Numbers

    end = Numbers.end() ;       // one past the location
                                // last element of Numbers

    //sort Numbers using the function object less<int>()
    //upper_bound assumes that Numbers is sorted
    //using the "compare" (less<int>() in this case)
    //function
    sort(start, end, less<int>()) ;

    // print content of Numbers
    cout << "Numbers { " ;
    for(it = start; it != end; it++)
        cout << *it << " " ;
    cout << " }\n" << endl ;

    //return the highest location at which 10 can be inserted
    // in Numbers
    location = upper_bound(start, end, 10, less<int>()) ;

    cout << "Last location  for element 10 in Numbers is: "
        << location - start << endl ;
}

Program Output is:

Numbers { 4 10 10 30 69 70 96 100  }

Last location  for element 10 in Numbers is: 3


Vector Class, operator== (STL Sample)

The sample code below illustrates how to use the vector class operator== STL function in Visual C++.

Required Header:
<vector>

Prototype:

template<class _TYPE, class _A> inline
     bool operator==(const vector<_TYPE, _A>& _X,
     const vector<_TYPE, _A>& _Y);

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
The sample declares three empty vectors, of a user-defined class called ID, each of which contains a Name string member and a Score integer member. It creates three vectors of IDs, then compares vectors using the operator== as defined for ID.

Sample Code:

//////////////////////////////////////////////////////////////////////
//
// Compile options needed: /GX
//
//    Opequal.cpp : Illustrates how to define the operator== to compare
//                  vectors.
//
// Functions:
//
//    vector::operator== - Vector equality comparison.
//    vector::push_back - Appends (inserts) an element to the end of a
//                        vector, allocating memory for it if necessary.
//
//////////////////////////////////////////////////////////////////////

// The debugger can't handle symbols more than 255 characters long.
// STL often creates symbols longer than that.
// When symbols are longer than 255 characters, the warning is disabled.
#pragma warning(disable:4786)

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>

using namespace std ;
using namespace std::rel_ops ;

// The ID class is used for team scoring. It holds each player's name
// and score.
class ID
{
public:
    string Name;
    int Score;

    ID() : Name(""), Score(0) {}
    ID(string NewName, int NewScore) : Name(NewName), Score(NewScore) {}
};

// In this example, an ID is equivalent only if both name and score match.
bool operator==(const ID& x, const ID& y)
{
    return (x.Name == y.Name) && (x.Score == y.Score);
}

// IDs will be sorted by Score, not by Name.
bool operator<(const ID& x, const ID& y)
{
    return x.Score < y.Score;
}

// Define a template class for a vector of IDs.
typedef vector<ID> NAMEVECTOR;

void main()
{
    // Declare 3 dynamically allocated vectors of names.
    NAMEVECTOR Vector1, Vector2, Vector3;

    // Create 3 short vectors of names.
    Vector1.push_back(ID("Karen Palmer", 2));
    Vector1.push_back(ID("Ada Campbell", 1));

    Vector2.push_back(ID("John Woloschuk", 3));
    Vector2.push_back(ID("Grady Leno", 2));

    Vector3.push_back(ID("Karen Palmer", 2));
    Vector3.push_back(ID("Ada Campbell", 1));

    // Compare Vector1 to Vector2 and show whether they're equivalent.
    Vector1 == Vector2 ? cout << "Vector1 == Vector2"
                       : cout << "Vector1 != Vector2";
    cout << endl;

    // Compare Vector1 to Vector3 and show whether they're equivalent.
    Vector1 == Vector3 ? cout << "Vector1 == Vector3"
                       : cout << "Vector1 != Vector3";
    cout << endl;

Program Output is:

Vector1 != Vector2
Vector1 == Vector3


vector::empty, erase, and push_back (STL Sample)

The sample code below illustrates how to use the vector::(empty, erase, push_back) STL functions in Visual C++.

Required Header:
<vector>

Prototype:

template<class _TYPE, class _A>
     void vector::push_back(const _TYPE& X);

template<class _TYPE, class _A>
     iterator vector::erase(iterator Iterator);

template<class _TYPE, class _A>
    iterator vector::erase(iterator First, iterator Last);

template<class _TYPE, class _A>
    bool vector::empty() const;

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
The sample declares an empty vector of integers. It adds 10 integers to the vector, then displays the contents of the vector. It deletes the sixth element by using erase, and then displays the contents of the vector again. It deletes the rest of the elements using a different form of erase, then displays the vector (now empty) again. The ShowVector routine uses the empty function to determine whether to generate the contents of the vector.

Sample Code:

//////////////////////////////////////////////////////////////////////
//
// Compile options needed: /GX
//
//    Empty.cpp -- Illustrates the vector::empty and vector::erase
//                 functions.
//                 Also demonstrates the vector::push_back function.
//
// Functions:
//
//    vector::empty - Returns true if vector has no elements.
//
//    vector::erase - Deletes elements from a vector (single & range).
//
//    vector::begin - Returns an iterator to start traversal of the
//                    vector.
//
//    vector::end - Returns an iterator for the last element of the
//                  vector.
//
//    vector::push_back - Appends (inserts) an element to the end of a
//                        vector, allocating memory for it if necessary.
//
//    vector::iterator - Traverses the vector.
//
//////////////////////////////////////////////////////////////////////

// The debugger can't handle symbols more than 255 characters long.
// STL often creates symbols longer than that.
// When symbols are longer than 255 characters, the warning is disabled.
#pragma warning(disable:4786)

#include <iostream>
#include <vector>

using namespace std ;

typedef vector<int> INTVECTOR;

const ARRAY_SIZE = 10;

void ShowVector(INTVECTOR &theVector);

void main()
{
    // Dynamically allocated vector begins with 0 elements.
    INTVECTOR theVector;

    // Intialize the vector to contain the numbers 0-9.
    for (int cEachItem = 0; cEachItem < ARRAY_SIZE; cEachItem++)
        theVector.push_back(cEachItem);

Program Output is:

    // Using void iterator erase(iterator Iterator) to
    // delete the 6th element (Index starts with 0).
    theVector.erase(theVector.begin() + 5);

    // Output the contents of the dynamic vector of integers.
    ShowVector(theVector);

    // Using iterator erase(iterator First, iterator Last) to
    // delete a range of elements all at once.
    theVector.erase(theVector.begin(), theVector.end());

    // Show what's left (actually, nothing).
    ShowVector(theVector);
}

// Output the contents of the dynamic vector or display a
// message if the vector is empty.
void ShowVector(INTVECTOR &theVector)
{
    // First see if there's anything in the vector. Quit if so.
    if (theVector.empty())
    {
        cout << endl << "theVector is empty." << endl;
        return;
    }

    // Iterator is used to loop through the vector.
    INTVECTOR::iterator theIterator;

    // Output contents of theVector.
    cout << endl << "theVector [ " ;
    for (theIterator = theVector.begin(); theIterator != theVector.end();
         theIterator++)
    {
        cout << *theIterator;
        if (theIterator != theVector.end()-1) cout << ", ";
                                              // cosmetics for the output
    }
    cout << " ]" << endl ;
}

Program Output is:

theVector [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ]

theVector [ 0, 1, 2, 3, 4, 6, 7, 8, 9 ]

theVector is empty.


vector::front and vector::back (STL Sample)

The sample code below illustrates how to use the vector::front and vector::back STL functions in Visual C++.

Required Header:
<vector>

Prototype:

template<class _TYPE, class _A>
    reference vector::front();

template<class _TYPE, class _A>
    reference vector::back();

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
The sample declares an empty vector of integers with the members [100, 200, 300, 400]. It displays the first element of the vector using vector::front to obtain it. It displays the last element of the vector using vector::back to obtain it. It displays the number of elements of the vector using vector::size. The sample erases the last element of the vector using vector::end()-1, and then displays the new last element using vector::back. It erases the first element of the vector using vector::begin, and then displays the new first element using vector::front. Finally, the sample displays the number of elements remaining in the vector using vector::size.

Sample Code:

//////////////////////////////////////////////////////////////////////
//
// Compile options needed: /GX
//
//    front.cpp: Illustrates the vector::front and vector::back methods.
//
// Functions:
//
//    vector::front - Returns reference to first element of vector.
//
//    vector::back - Returns reference to last element of vector.
//
//    vector::push_back - Appends (inserts) an element to the end of a
//                        vector, allocating memory for it if necessary.
//
//    vector::size - Returns number of elements in the vector.
//
//    vector::begin - Returns an iterator to start traversal of the vector.
//
//    vector::end - Returns an iterator for the last element of the vector.
//
//    vector::erase - Deletes elements from a vector (single & range).
//
//////////////////////////////////////////////////////////////////////

// The debugger can't handle symbols more than 255 characters long.
// STL often creates symbols longer than that.
// When symbols are longer than 255 characters, the warning is issued.
#pragma warning(disable:4786)

#include <iostream>
#include <vector>

using namespace std ;

typedef vector<int> INTVECTOR;

const ARRAY_SIZE = 4;

void main()
{
    // Dynamically allocated vector begins with 0 elements.
    INTVECTOR theVector;

    // Intialize the array to contain the members [100, 200, 300, 400]
    for (int cEachItem = 0; cEachItem < ARRAY_SIZE; cEachItem++)
        theVector.push_back((cEachItem + 1) * 100);

    cout << "First element: " << theVector.front() << endl;
    cout << "Last element: " << theVector.back() << endl;
    cout << "Elements in vector: " << theVector.size() << endl;

    // Delete the last element of the vector. Remember that the vector
    // is 0-based, so theVector.end() actually points 1 element beyond
    // the end.
    theVector.erase(theVector.end() - 1);

    cout << endl << "After erasing last element, new last element is: "
         << theVector.back() << endl;

    // Delete the first element of the vector.
    theVector.erase(theVector.begin());

    cout << "After erasing first element, new first element is: "
         << theVector.front() << endl;

    cout << "Elements in vector: " << theVector.size() << endl;
}

Program Output is:

First element: 100
Last element: 400
Elements in vector: 4

After erasing last element, new last element is: 300
After erasing first element, new first element is: 200
Elements in vector: 2


Vector Class, operator< (STL Sample)

The sample code below illustrates how to use the the vector class operator< STL function in Visual C++.

Required Header:
<vector>

Prototype:

template<class _TYPE, class _A> inline
     bool operator<(const vector<_TYPE, _A>& _X,
     const vector<_TYPE, _A>& _Y);

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
The sample declares an empty vector of IDs, a user-defined type. It initializes and adds four IDs to the vector in random order. It sorts them using the operator< defined for ID and generates the newly sorted vector. (Note that it sorts in order of Score, not Name.)

Sample Code:

//////////////////////////////////////////////////////////////////////
//
// Compile options needed: /GX
//
//    Opless.cpp -- Illustrates the defining the < operator to sort vectors
//
// Functions:
//
//    operator< - Vector comparison operator.
//
//    vector::begin - Returns an iterator to start traversal of the vector.
//
//    vector::end - Returns an iterator for the last element of the vector.
//
//    vector::iterator - Traverses the vector.
//
//    vector::push_back - Appends (inserts) an element to the end of a
//                        vector, allocating memory for it if necessary.
//
//    sort algorithm - Sorts the vector.
//
//////////////////////////////////////////////////////////////////////

// The debugger can't handle symbols more than 255 characters long.
// STL often creates symbols longer than that.
// When symbols are longer than 255 characters, the warning is disabled.
#pragma warning(disable:4786)

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>

using namespace std ;

// The ID class is used for team scoring. It holds each player's name
// and score.
class ID
{
public:
    string Name;
    int Score;
    ID() : Name(""), Score(0) {}
    ID(string NewName, int NewScore) : Name(NewName), Score(NewScore) {}
};

// In this example, an ID is equivalent only if both name and score match.
bool operator==(const ID& x, const ID& y)
{
    return (x.Name == y.Name) && (x.Score == y.Score);
}

// IDs will be sorted by Score, not by Name.
bool operator<(const ID& x, const ID& y)
{
    return x.Score < y.Score;
}

// Define a template class for a vector of IDs.
typedef vector<ID> NAMEVECTOR;

void main()
{
    // Declare a dynamically allocated vector of IDs.
    NAMEVECTOR theVector;

    // Iterator is used to loop through the vector.
    NAMEVECTOR::iterator theIterator;

    // Create a pseudo-random vector of players and scores.
    theVector.push_back(ID("Karen Palmer", 2));
    theVector.push_back(ID("Ada Campbell", 1));
    theVector.push_back(ID("John Woloschuk", 3));
    theVector.push_back(ID("Grady Leno", 2));

    for (theIterator = theVector.begin(); theIterator != theVector.end();
         theIterator++)
        cout << theIterator->Score  << "\t"
             << theIterator->Name << endl;
    cout << endl;

    // Sort the vector of players by score.
    sort(theVector.begin(), &theVector[theVector.size()]);

    // Output the contents of the vector in its new, sorted order.
    cout << "Players ranked by score:" << endl;
    for (theIterator = theVector.begin(); theIterator != theVector.end();
         theIterator++)
        cout << theIterator->Score  << "\t"
             << theIterator->Name << endl;
    cout << endl << endl;
}

Program Output is:

Players and scores:
2       Karen Palmer
1       Ada Campbell
3       John Woloschuk
2       Grady Leno

Players ranked by score:
1       Ada Campbell
2       Karen Palmer
2       Grady Leno
3       John Woloschuk


vector::push_back and vector::pop_back (STL Sample)

The sample code below illustrates how to use the vector::push_back and vector::pop_back STL functions in Visual C++.

Required Header:
<vector>

Prototype:

template<class _TYPE, class _A>
     void vector::push_back(const _TYPE& X);

template<class _TYPE, class _A>
    void vector::pop_back();

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
The sample declares an empty vector of integers. It adds three integers to the vector, and then deletes one. Finally, it generates the remaining elements in the vector.

Sample Code:

//////////////////////////////////////////////////////////////////////
//
// Compile options needed: /GX
//
// Pushpop.cpp: Illustrates how to use the push and pop member
//              functions of the vector container.
//
// Functions:
//
//    vector::push_back - Appends (inserts) an element to the end of a
//                        vector, allocating memory for it if necessary.
//
//    vector::pop_back -  Erases the last element of the vector.
//
//    vector::begin - Returns an iterator to start traversal of the vector.
//
//    vector::end - Returns an iterator for the last element of the vector.
//
//    vector::iterator - Traverses the vector.
//
//////////////////////////////////////////////////////////////////////

// The debugger can't handle symbols more than 255 characters long.
// STL often creates symbols longer than that.
// When symbols are longer than 255 characters, the warning is disabled.
#pragma warning(disable:4786)

#include <iostream>
#include <vector>

using namespace std ;

typedef vector<int> INTVECTOR;

void main()
{
    // Dynamically allocated vector begins with 0 elements.
    INTVECTOR theVector;

    // Iterator is used to loop through the vector.
    INTVECTOR::iterator theIterator;

    // Add one element to the end of the vector, an int with the value 42.
    // Allocate memory if necessary.
    theVector.push_back(42) ;

    // Add two more elements to the end of the vector.
    // theVector will contain [ 42, 1, 109 ].
    theVector.push_back(1) ;
    theVector.push_back(109) ;

    // Erase last element in vector.
    theVector.pop_back();

    // Print contents of theVector. Shows [ 42, 1 ]
    cout << "theVector [ " ;
    for (theIterator = theVector.begin(); theIterator != theVector.end();
         theIterator++)
    {
        cout << *theIterator;
        if (theIterator != theVector.end()-1) cout << ", ";

    }
    cout << " ]" << endl ;
}

Program Output is:

theVector [ 42, 1 ]


vector::size, vector::capacity, and more (STL Sample)

The sample code below illustrates how to use the vector::size and vector::capacity STL functions in Visual C++.

Required Header:
<vector>

Prototype:

template<class _TYPE, class _A>
     void vector::reserve(size_type _N);

template<class _TYPE, class _A>
     size_type vector::max_size() const;

template<class _TYPE, class _A>
     void vector::resize(size_type _N, _TYPE _X = _TYPE());

template<class _TYPE, class _A>
     size_type vector::capacity() const;

template<class _TYPE, class _A>
     size_type vector::size() const;

Note: The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.

Description:
The sample declares an empty vector of integers. It adds a single integer element to the vector, and then shows information about the vector's size, maximum size, and capacity. It reserves storage for 1000 elements and displays the same information about the vector. Finally, it resizes the vector to 2000 elements, and then displays the information.

Sample Code:

//////////////////////////////////////////////////////////////////////
//
// Compile options needed: /GX
//
//    Remax.cpp: Illustrates vector::reserve, vector::max_size,
//               vector::resize, vector::resize, and vector::capacity.
//
// Functions:
//
//    vector::max_size - Returns maximum number of elements vector could
//                       hold.
//
//    vector::capacity - Returns number of elements for which memory has
//                       been allocated.
//
//    vector::size - Returns number of elements in the vector.
//
//    vector::resize - Reallocates memory for vector, preserves its
//                     contents if new size is larger than existing size.
//
//    vector::reserve - Allocates elements for vector to ensure a minimum
//                      size, preserving its contents if the new size is
//                      larger than existing size.
//
//    vector::push_back - Appends (inserts) an element to the end of a
//                        vector, allocating memory for it if necessary.
//
//////////////////////////////////////////////////////////////////////

// The debugger can't handle symbols more than 255 characters long.
// STL often creates symbols longer than that.
// When symbols are longer than 255 characters, the warning is disabled.
#pragma warning(disable:4786)

#include <iostream>
#include <vector>

using namespace std ;

typedef vector<int> INTVECTOR;

void main()
{
    // Dynamically allocated vector begins with 0 elements.
    INTVECTOR theVector;

    // Add one element to the end of the vector, an int with the value 42.
    theVector.push_back(42) ;

    // Show statistics about vector.
    cout << "theVector's size is: " << theVector.size() << endl;
    cout << "theVector's maximum size is: " << theVector.max_size()
         << endl;
    cout << "theVector's capacity is: " << theVector.capacity() << endl;

    // Ensure there's room for at least 1000 elements.
    theVector.reserve(1000);
    cout << endl << "After reserving storage for 1000 elements:" << endl;
    cout << "theVector's size is: " << theVector.size() << endl;
    cout << "theVector's maximum size is: " << theVector.max_size()
         << endl;
    cout << "theVector's capacity is: " << theVector.capacity() << endl;

    // Ensure there's room for at least 2000 elements.
    theVector.resize(2000);
    cout << endl << "After resizing storage to 2000 elements:" << endl;
    cout << "theVector's size is: " << theVector.size() << endl;
    cout << "theVector's maximum size is: " << theVector.max_size()
         << endl;
    cout << "theVector's capacity is: " << theVector.capacity() << endl;
}

Program Output is:

theVector's size is: 1
theVector's maximum size is: 1073741823
theVector's capacity is: 1

After reserving storage for 1000 elements:
theVector's size is: 1
theVector's maximum size is: 1073741823
theVector's capacity is: 1000

After resizing storage to 2000 elements:
theVector's size is: 2000
theVector's maximum size is: 1073741823
theVector's capacity is: 2000


Topic Not Found

No matching topic was found. Some possible reasons and remedies are as follows:

  • The file (.chm) that contains the destination topic is not in the expected location.

    • Remedy: Rerun the MSDN Library Setup.

  • The file (.chm) that contains the current topic or destination topic is out-of-date and the link is no longer valid.

    • Remedy: Install the latest version of the MSDN Library.

  • The MSDN Library CD is not in the CD-ROM drive.

    • Remedy: Insert the MSDN Library CD into the CD-ROM drive.


Topic Not Found

No matching topic was found. Some possible reasons and remedies are as follows:

  • The file (.chm) that contains the destination topic is not in the expected location.

    Remedy: Rerun the MSDN Library Setup.

  • The file (.chm) that contains the current topic or destination topic is out-of-date and the link is no longer valid.

    Remedy: Install the latest version of the MSDN Library.

  • The MSDN Library CD is not in the CD-ROM drive.

    Remedy: Insert the MSDN Library CD into the CD-ROM drive.