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. The macro assert is encouraged to display the current function, as specified by the new preprocessor macro __func__, as part of its diagnostic message. 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, complex, and complex. So it is not strictly necessary to add the builtin complex types of C99 to C++. Our version of includes 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 . Our implementation also provides the added header , with the usual namespace implications. The function isblank, which matches at least space and tab (plus other locale-specific blank characters outside the "C" locale), is added with C99. The new header 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 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 , with the usual namespace implications. C99 requires that all macros defined in 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 . The header also adds the macros FLT_EVAL_METHOD and DECIMAL_DIG. The new header , which supplements the new header , 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 . 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 , with the usual namespace implications. 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 as well. If C++ adds long long types, these additions are also needed. 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. 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. The new header 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 , just for completeness (much like ). The new header 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 , with the usual namespace implications. 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. 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. The new header declares generic versions of all the functions declared in and . 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), 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 , with the usual namespace implications. C99 adds the functions wcstof, wcstold, wcstoll, wcstoull. Same comments as for the additions to . 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 and ) 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.