ISO/ IEC JTC1/SC22/WG21 N1372

Doc. No.: N1372 = 02-0030

Proposed C99 Library Additions to C++ (Revised)
P.J. Plauger
Dinkumware, Ltd.

The revised C standard ISO 9899:1999 (a.k.a. C99) makes extensive additions
to the Standard C library. The most obvious ones live in six new headers,
but the 18 existing headers (15 from C89 and 3 from Amendment 1) also have
a host of additions. I summarize here what has been added since the C++
Standard froze (ISO 14882:1998), along with some suggestions for appropriate
C++ machinery to accompany the new stuff. For a more complete description,
see the Dinkum C99 Library Reference at http://www.dinkumware.com/refxc.html,
which closely reflects the material summarized here. Note that Dinkumware
has been shipping a combined C99/C++ library for the past year, so all of
the proposed C++ additions have been implemented.

As requested at the Curacao meeting, I have eliminated all commentary on
the language proper. This document focuses as purely as possible on
library issues.


SUMMARY OF C99 ADDITIONS AND CHANGES

Here is a brief summary of all the features added to the library with C99,
since C was last amended in 1995. (C++ incorporates C90 plus Amendment 1
by reference.) I've left out all the places where function pointer arguments
now have the restrict access qualifier. I've also left out any number of small
tweaks to the semantics of individual functions.

<assert.h>

The macro assert is encouraged to display the current function, as specified
by the new preprocessor macro __func__, as part of its diagnostic message.

<complex.h>

C99 adds the three types float _Complex, double _Complex, and long double
_Complex, with Fortran-ish interconversion rules with the existing real
types. The header complex.h also regrettably defines the macro complex, as
a synonym for the keyword _Complex. Obviously, this definition should not
be present in C++. Less obviously, all the added math functions declared in
this header should work properly for complex<float>, complex<double>, and
complex<long double>. So it is not strictly necessary to add the builtin
complex types of C99 to C++.

Our version of <complex.h> includes <complex> and ensures that overloads
exist for the C++ complex types, for at least the functions acos, acosh,
asin, asinh, atan, atanh, and fabs, none of which are declared in
<complex>.

Our implementation also provides the added header <ccomplex>, with the
usual namespace implications.

<ctype.h>

The function isblank, which matches at least space and tab (plus other
locale-specific blank characters outside the "C" locale), is added with
C99.

<fenv.h>

The new header <fenv.h> declares a host of functions for controlling a
floating-point processor (FPP), if it happens to look enough like an
IEEE-754 (IEC 60559) FPP. It gives programs an added level of control over
rounding modes, floating-point traps, etc. that is important to some
sophisticated numeric programs.

Our implementation provides reasonably uniform support for <fenv.h> across
a dozen of the most popular computer architectures. GLIBC has done about
the same. So this seems to be a useful addition to C++.

Our implementation also provides the added header <cfenv>, with the
usual namespace implications.

<float.h>

C99 requires that all macros defined in <float.h> be constant expressions.
(FLT_ROUNDS still has the added requirement that it be usable in an #if
expression.) That's really only possible with the addition of hexadecimal
floating-point constants to C99. So C++ would have to adopt this notation
if it were to add the same constraint to <float.h>.

The header also adds the macros FLT_EVAL_METHOD and DECIMAL_DIG.

<inttypes.h>

The new header <inttypes.h>, which supplements the new header <stdint.h>,
declares several functions for manipulating values of type intmax_t,
a synonym for the largest integer type. It also defines a slew of
macros that supply the appropriate scan and print conversion specifiers
for the integer types defined in <stdint.h>. While the printf/scanf
additions are less attractive for C++, the added integer types have
proved useful in the field. It is probably sufficient to just adopt
the same printf/scanf conversion specifiers and not muck up the
iostreams machinery to deal with the additional types.

Our implementation adds overloads in C++ for the functions abs and div.

Our implementation also provides the added header <cinttypes>, with the
usual namespace implications.

<limits.h>

C99 adds macros LLONG_MIN, LLONG_MAX, and ULLONG_MAX, for the new long long
and unsigned long long types. Our implementation adds the obvious template
specializations to <limits> as well. If C++ adds long long types, these
additions are also needed.

<math.h>

C99 adds all sorts of stuff:

-- macros FP_FAST_FMA, FP_FAST_FMAF, FP_FAST_FMAL to signal the presence of
fused multiply/add

-- macros FP_ILOGB0, FP_ILOGBNAN for error returns from function ilogb

-- macros FP_INFINITE, FP_NAN, FP_NORMAL, FP_SUBNORMAL, FP_ZERO for category
returns from macro fpclassify

-- macros HUGE_VALF, HUGE_VALL to supplement HUGE_VAL

-- macros INFINITY, NAN for special floating-point values

-- macros MATH_ERRNO, MATH_ERREXCEPT, math_errhandling to describe handling of
math errors

-- function macros signbit, fpclassify, isfinite, isinf, isnan, isnormal,
isgreater, isgreaterequal, isless, islessequal, islessgreater, isunordered
to test floating-point values

-- types double_t and float_t for tighter control over computational
types

-- functions acosh, asinh, atanh, cbrt, copysign, erf, erfc, exp2, expm1,
fdim, fma, fmax, fmin, hypot, ilogb, lgamma, llrint, llround, log1p, log2,
logb, lrint, lround, nan, nearbyint, nextafter, nexttoward, remainder,
remquo, rint, round, scalbln, scanbn, tgamma, and trunc, plus float
versions (ending in f) and long double versions (ending in l)

Our implementation replaces the function macros (signbit, etc.) with
inline functions in C++. It also adds overloads for all the new functions,
following the same pattern as in the current C++ Standard (acosh(float)
and acosh(long double), for example). Note that there is no portable way
to write the macros INFINITY and NAN, not even in C99. Some language
change is needed, such as requiring/permitting 1.0/0.0 and 0.0/0.0 to
have the same compile-time meaning as in Java.

<stdarg.h>

C99 adds the macro va_copy(va_list), to copy a va_list object. This is
a good idea since va_list may or may not be an array type.

<stdbool.h>

The new header <stdbool.h> defines the macros bool (as the builtin type
_Bool), true, false, and __bool_true_false_are_defined. In C++, all but
the last of these macros should be left undefined, of course. The C99
semantics for bool were intended to match those of C++.

Our implementation also provides the added header <cstdbool>, just for
completeness (much like <ciso646>).

<stdint.h>

The new header <stdint.h> defines a whole slew of types, of the form:

	[u]int[fast least]{8 16 32 64}_t
	[u]int{max ptr}_t

and another slew of macros, of the form:

	INT[FAST LEAST]{8 16 32 64}_MIN
	[U]INT[FAST LEAST]{8 16 32 64}_MAX
	INT{MAX PTR}_MIN
	[U]INT{MAX PTR}_MAX
	{SIG_ATOMIC WCHAR WINT}{_MAX _MIN}
	SIZE_MAX

plus function macros (for converting literals to a known type) of the
form:

	[U]INT{8 16 32 64}_C

As I mentioned earlier, these seem to be a useful addition, for some styles
of programming.

Our implementation also provides the added header <cstdint>, with the
usual namespace implications.

<stdio.h>

C99 adds the functions snprintf, vfprintf, vprintf, vsnprintf, vprintf,
vfscanf, vscanf, and vsscanf. To the print and scan functions, it adds
the conversion specifiers a (for hexadecimal floating-point) and F, and
the conversion qualifiers hh, h, ll, t, and z (for various integer types).
It also defines the text forms of infinity and NaN values. It is not yet
clear to me that all these options need to be added to iostreams as
well.

<stdlib.h>

C99 adds the type lldiv_t, and the functions atoll, llabs, lldiv, strtof,
strtold, strtoll, strtoull, and _Exit. Most of these are contingent on
the addition of long long types, but all are useful.

Our implementation adds the obvious overloads to C++ for abs and div.

<tgmath.h>

The new header <tgmath.h> declares generic versions of all the functions
declared in <complex.h> and <math.h>. These follow Fortran-style rules
for determining which version of a function to call, based on the argument
type. For example, sqrt(2.0) calls sqrt(double), sqrt(2.0F) calls
sqrt(float), and sqrt(2) calls sqrt(double). While this requires compiler
magic in C, the same rules can be implemented in C++ by the addition of
a single template function for each of the overloaded functions. (Note that,
without such a template assist, the call sqrt(2) is ambiguous in C++ if the
only visible overloads are sqrt(float), sqrt(complex<float>), etc.)

Our implementation provides these added template overloads in C++, to
ensure that overload resolution is the same in either C or C++.

Our implementation also provides the added header <ctgmath>, with the
usual namespace implications.

<wchar.h>

C99 adds the functions wcstof, wcstold, wcstoll, wcstoull. Same comments
as for the additions to <stdlib.h>.

<wctype.h>

C99 adds the function iswblank.


RECOMMENDATION

C++ should incorporate by reference all the library facilities added with
C99, except for the macros that conflict in obvious ways, as described
above. It should also adopt the added function overloads and macro
replacements that we have found to be successful with our implementation.
While some features (such as <inttypes.h> and <stdbool.h>) are of marginal
utility in C++, they are no worse than C features already incorporated in
Standard C++. Completeness leads to fewer surprises.

C++ should also consider extending the iostreams formatting notation to
deal with hexadecimal floating-point format and the added integer type
definitions.

This proposal is contingent in part on whether C++ adopts several C99
language features:

-- adding long long integers

-- adding hexadecimal floating-point literals

I've tried to indicate what should be omitted from the library if either
or both of these features are not adopted.

This proposal does NOT recommend:

-- adding the keyword _Complex, and builtin complex arithmetic, to C++

-- adding the keyword _Bool, as a synonym for bool, to C++

Neither is necessary to achieve a reasonable level of compatibility
between C99 and C++, and the former causes major headaches in C++.

This proposal makes NO recommendation about:

-- adding compound (and designated) literals

-- defining __STDC_VERSION__ as some value greater than 199901L

-- adding the keyword restrict, and restriced pointer semantics, to C++

-- adding variable-length arrays to C++

-- adding __func__ and function macros with variable-length argument lists
to the preprocessor

Compatibility between the C99 and C++ libraries is not seriously compromised
by the absence of any of these features in C++. Each should be addressed as
a language addition on its own merits.