The language support section of the Standard C++ Library provides common type definitions used throughout the library, characteristics of pre-defined types, functions supporting start and termination of C++ programs, support for dynamic memory allocation, support for dynamic type identification, support for exception processing, and other run-time support.
This header file basically includes stddef.h. There are two macros, NULL and offsetof, and two types, ptrdiff_t and size_t, specifically listed in this section of the standard.
To determine the distance (or the number of elements) between two elements you can use the distance() function. If you pass it an iterator pointing to the first element and one pointing to the third element, it will return a 2.
The distance function is in the utility header file and it takes two iterators as parameters and returns a number of type difference_type. Difference_type maps is an int. The sequence is:
typedef _PDFT difference_type
#define _PDFT ptrdiff_t
typedef int ptrdiff_t
Note With Visual C++ 4.2 the online help states the difference function takes 3 parameters and returns void. For example:
template <class Init, class Dist>
void distance(InIt first, InIt last, Dist&n);
However, it actually takes two parameters and returns a value, as follows:
template <class Init, class Dist>
Dist distance(InIt first, InIt last)
The following example demonstrates the distance() function:
#include <iostream>
#include <vector>
#include <iterator>
#include <string>
#pragma warning (disable:4786)
typedef vector<string, allocator<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;
}
The 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
The numeric_limits component provides information about properties of fundamental types. Specializations are provided for each fundamental type such as int, floating point, and bool. The member is_specialized returns true for the specializations of numeric_limits for the fundamental types
The numeric_limits class is defined in the limits header file.
template<class T> class numeric_limits {
public:
static const bool has_denorm;
static const bool has_denorm_loss;
static const bool has_infinity;
static const bool has_quiet_NaN;
static const bool has_signaling_NaN;
static const bool is_bounded;
static const bool is_exact;
static const bool is_iec559;
static const bool is_integer;
static const bool is_modulo;
static const bool is_signed;
static const bool is_specialized;
static const bool tinyness_before;
static const bool traps;
static const float_round_style round_style;
static const int digits;
static const int digits10;
static const int max_exponent;
static const int max_exponent10;
static const int min_exponent;
static const int min_exponent10;
static const int radix;
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();
};
Table 13 describes the member functions of the numeric_limit class.
Table 13. Member Functions of the numeric_limit Class
Member function | Description |
has_denorm | Stores true for a floating-point type that has denormalized values (effectively a variable number of exponent bits). |
has_denorm_loss | 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 and not subject to limitations of exponent range and precision). |
has_infinity | The member stores true for a type that has a representation for positive infinity. True if is_iec559 is true. |
has_quiet_NaN | Stores true for a type that has a representation for a quiet NaN, an encoding that is "Not a Number'' which does not signal its presence in an expression. True if is_iec559 is true. |
has_signaling_NaN | The member stores true 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. |
is_bounded | Stores true for a type that has a bounded set of representable values (which is the case for all predefined types). |
is_exact | 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. |
is_iec559 | 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 USA). |
is_integer | Stores true for a type that has an integer representation. |
is_modulo | Stores true for a type that has a modulo representation, where all results are reduced modulo some value. |
is_signed | Stores true for a type that has a signed representation (which is the case for all predefined floating-point and signed integer types). |
is_specialized | Stores true for a type that has an explicit specialization defined for template class numeric_limits. |
tinyness_before | Stores true for a type that determines whether a value is ``tiny'' (too small to represent as a normalized value) before rounding. |
traps | Stores true for a type that generates some kind of signal to report certain arithmetic exceptions. |
round_style |
Stores a value that describes the various
methods that an implementation can choose for rounding a floating-point
value to an integer value. The round styles are: enum float_round_style { round_indeterminate = -1, round_toward_zero = 0, round_to_nearest = 1, round_toward_infinity = 2, round_toward_neg_infinity = 3 |
digits | 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). |
digits10 | Stores the number of decimal digits that the type can represent without change. |
max_exponent | The member stores the maximum positive integer 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. |
max_exponent10 | The member stores the maximum positive integer 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. |
min_exponent | The member stores the minimum negative integer 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. |
min_exponent10 | The member stores the minimum negative integer 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. |
radix; | 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(which is FLT_RADIX for the predefined floating-point types). |
denorm_min() | The function returns the minimum value for the type (which is the same as min() if has_denorm is False). |
epsilon() | 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). |
infinity() | The function returns the representation of positive infinity for the type. The return value is meaningful only if has_infinity is true. |
max() | 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. |
min() | 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. |
quiet_ Nan() | The function returns a representation of a quiet NaN for the type. The return value is meaningful only if has_quiet_NaN is true. |
round_error() | The function returns the maximum rounding error for the type. |
Signaling_Nan() | The function returns a representation of a signaling NaN for the type. The return value is meaningful only if has_signaling_NaN is true. |
The following example demonstrates the numeric_limits class member functions:
#include <iostream>
#include <limits>
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 representble 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;
}
Output:
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 a integer an integer? 1
11 Is a float an integer? 0
12 Is a 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
Additional values defined from the <climits> and <cfloat> header files which include <limits.h> and float.h, respectively, are:
CHAR_BIT INT_MAX LONG_MIN SCHAR_MIN UCHAR_MAX
CHAR_MAX INT_MIN MB_LEN_MAX SHRT_MAX UINT_MAX
CHAR_MIN LONG_MAX SCHAR_MAX SHRT_MIN ULONG_MAX
USHRT_MAX
DBL_DIG DBL_MIN_EXP FLT_MIN_10_EXP LDBL_MAX_10_EXP
DBL_EPSILON FLT_DIG FLT_MIN_EXP LDBL_MAX_EXP
DBL_MANT_DIG FLT_EPSILON FLT_RADIX LDBL_MIN
DBL_MAX FLT_MANT_DIG FLT_ROUNDS LDBL_MIN_10_EXP
DBL_MAX_10_EXP FLT_MAX LDBL_DIG LDBL_MIN_EXP
DBL_MAX_EXP FLT_MAX_10_EXP LDBL_EPSILON
DBL_MIN FLT_MAX_EXP LDBL_MANT_DIG
DBL_MIN_10_EXP FLT_MIN LDBL_MAX
Note The LDBLxxx constants are not listed in the online help for Visual C++ 4.2 but they are defined in <float.h>
There are two additional constants defined in the Visual C++ 4.2 implementation that are not a part of the Standard C++ Library, they are:
_DBL_RADIX
_DBL_ROUNDS
See the online help with Visual C++ 4.2 for descriptions of these constants.
The cstdlib header file includes the C header file <cstdlib.h>. Table 14 lists the functions specified.
Table 14. Functions Specified in cstdlib
Function | Description |
void abort( void ); | Aborts the current process and returns an error code. |
int atexit( void ( __cdecl *func )( void ) ); | Processes the specified function at exit. |
void exit( int status ); | Terminate the calling process after cleanup (exit) or immediately (_exit). |
The online help for the new header file
lists the following.
typedef void (*new_handler)();
class bad_alloc;
class nothrow;
new_handler set_new_handler(new_handler ph) throw();
void operator delete(void *p) throw();
void operator delete(void *, void *) throw();
void operator delete(void *p, const nothrow&) throw();
void operator delete[](void *p) throw();
void operator delete[](void *, void *) throw();
void operator delete[](void *p, const nothrow&) throw();
void *operator new(size_t n) throw(bad_alloc);
void *operator new(size_t n, const nothrow&) throw();
void *operator new(size_t n, void *p) throw();
void *operator new[](size_t n) throw(bad_alloc);
void *operator new[](size_t n, const nothrow&) throw();
void *operator new[](size_t n, void *p) throw();
The main thing to note is that there is support for the operator new either returning NULL or throwing an exception on failure.
The class nothrow{} is used as a function parameter to indicate that the function should never throw an exception.
The online help for the operator new in the Visual C++ 4.2 Standard C++ Library Reference is pretty good. Either query on 'operator new' or look in the help for the <new> header file.
In the above prototypes, don't let the throw(), throw you. Visual C++ 4.2 does not implement these exception specifications. This is noted in the online help.
Microsoft C++ does not support the function throw signature mechanism, as described in section 15.5 of the ANSI C++ draft.
Microsoft C++ does not support the function exception specification mechanism, as described in section 15.4 of the ANSI C++ draft.
An exception specification specifies the type of exceptions a function can throw, for example:
void Func() throw (ProblemOne, ProblemTwo) {}
is equivalent to:
void Func() {
{
try {}
catch (ProblemOne) {}
catch (ProblemTwo) {}
catch ( ) { unexpected(); }
}
These operators:
void *operator new(size_t n) throw(bad_alloc);
void *operator new[](size_t n) throw(bad_alloc);
will throw a bad_alloc exception if the memory allocation fails. Or if you define a new_handler function via set_new_handler, the new handler function will be called instead.
These operators:
void *operator new(size_t n, const nothrow&) throw();
void *operator new(size_t n, void *p) throw();
void *operator new[](size_t n, const nothrow&) throw();
void *operator new[](size_t n, void *p) throw();
will simply return NULL if the memory allocation fails.
In the following sample, 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, throw an exception.
#include <new>
#include <iostream>
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
Note that the above example uses the what() function to print out the type of exception. This function is a part of the exception class. The value returned by what() is implementation defined.
An important thing to note is that code which previously returned a NULL when a call to new failed will instead throw an exception if you use the standard C++ header files. This means that if you modify your code to include <new> then you also need to modify your code to check for an exception rather than checking to see if new returned NULL.
Intermixing old header files with the new standard C++ header files can cause multiple problems with the new operator. For example, if the following code:
class BigClass {
public:
BigClass() {};
~BigClass(){}
double BigArray[99999999];
};
void main() {
BigClass * q = new BigClass;
if ( q == NULL )
cout << "Returned a NULL pointer" << endl;
}
includes these header files, you get the noted results.
#include <iostream.h>
// No Errors.
#include <iostream.h>
#include <new>
// No errors - returns a NULL.
#include <new>
#include <iostream.h>
// No errors - returns a NULL.
#include <new>
#include <iostream>
// Throws an exception instead of returning NULL.
#include <iostream>
// Throws an exception instead of returning NULL.
If you are using the newer forms of the operator new such as:
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;
}
and include the following header files, you will get the noted results.
#include <new>
#include <iostream>
// No Errors.
#include <iostream>
#include <new>
// No Errors.
#include <iostream>
// No Errors.
#include <new>
//C:\MSDEV\Projects\defcon\Text5.cpp(40) : error C2065: 'cout' : undeclared identifier
//C:\MSDEV\Projects\defcon\Text5.cpp(40) : error C2297: '<<' : bad right operand
//C:\MSDEV\Projects\defcon\Text5.cpp(40) : error C2065: 'endl' : undeclared identifier
//C:\MSDEV\Projects\defcon\Text5.cpp(41) : error C2297: '<<' : bad right operand
//C:\MSDEV\Projects\defcon\Text5.cpp(45) : error C2297: '<<' : bad right operand
#include <new>
#include <iostream.h>
// ext5.obj : error LNK2001: unresolved external symbol "void * __cdecl operator new(unsigned int,struct nothrow_t const &)"(??2@YAPAXIABUnothrow_t@@@Z)
// Debug/defcon.exe : fatal error LNK1120: 1 unresolved externals
#include <iostream.h>
#include <new>
// Text5.obj : error LNK2001: unresolved external symbol "void * __cdecl operator new(unsigned int,struct nothrow_t const &)"(??2@YAPAXIABUnothrow_t@@@Z)
// Debug/defcon.exe : fatal error LNK1120: 1 unresolved external
#include <iostream.h>
//C:\MSDEV\Projects\defcon\Text5.cpp(47) : error C2061: syntax error : identifier 'bad_alloc'
//C:\MSDEV\Projects\defcon\Text5.cpp(47) : error C2310: catch handlers must specify one type
//C:\MSDEV\Projects\defcon\Text5.cpp(48) : error C2065: 'a' : undeclared identifier
//C:\MSDEV\Projects\defcon\Text5.cpp(48) : error C2228: left of '.what' must hav class/struct/union type
//C:\MSDEV\Projects\defcon\Text5.cpp(52) : error C2317: 'try' block starting on line '44' has no catch handlers
//C:\MSDEV\Projects\defcon\Text5.cpp(52) : error C2065: 'nothrow' : undeclared identifier
//C:\MSDEV\Projects\defcon\Text5.cpp(52) : error C2660: 'new' : function does not take 2 parameters
The <typeinfo> header defines a type associated with the type information generated by the implementation (type_info). It also defines two types for reporting dynamic type identification errors (bad_cast and bad_typeid).
The type_info class is defined with a raw_name member in the help and header files (in both Visual C++ and the library). However, in the current version of the C++ Library Standard, there is no raw_name member. The raw_name member function returns a const char* to a null-terminated string representing the decorated name of the object type.
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 exception class defines the base class for the types of objects thrown as exceptions by the C++ Standard Library components. The exception header file defines the exception class that is the base class for all exceptions thrown by the C++ Standard Library. The following code would catch any exception thrown by classes and functions in the Standard C++ Library:
try {
// code
}
catch ( const exception &ex) {
cout << "exception: " << ex.what();
}
The exception class is defined in the header file exception, as follows:
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();
private:
...
};
See Exception Handling and Standard C++ Library Diagnostics for further details.
With Visual C++ 4.2, each of these headers files includes the corresponding C header file, stdarg.h, setjmp.h, time.h, signal.h, and stdlib.h. Macros, types, and functions listed for each of these in the Standard C++ Library are as follows:
cstdarg
Macros: va_arg va_end va_start
Types: va_list
csetjmp
Macro: setjmp
Types: jmp_buf
Function: longjmp
ctime
Macros: CLOCKS_PER_SEC
Types: clock_t
Functions: clock
csignal
Macros: SIGABRT SIGILL SIGSEGV SIG_DFL
SIG_IGN SIGFPE SIGINT SIGTERM SIG_ERR
Types: sig_atomic_t
Functions: raise signal
cstdlib
Functions: getenv system