Branching from P0829R4. This "omnibus" paper is still the direction I am aiming for. However, it is too difficult to review. It needs to change with almost every meeting. Therefore, it is getting split up into smaller, more manageable chunks.
Limiting paper to <version>
, blanket wording, and freestanding facilities already in the working draft.
This paper is the first of many smaller papers adding facilities to the C++ freestanding library. This paper in particular will only be updating the editorial technique for declaring facilities as freestanding. This update will make it easier to mark headers as partially freestanding. This wording change will make it easier to mark in-flight proposals as freestanding, without causing a major blocking point in the standardization process.
Many existing facilities in the C++ standard library could be used without trouble in freestanding environments. This series of papers will specify the maximal subset of the C++ standard library that does not require an OS or space overhead.
For a more in depth rationale, see P0829.
This paper is going to add blanket wording to make it easier to mark things freestanding, and it will retrofit the existing freestanding facilities. It also includes a non-normative note that should allow implementers to use existing no-exception builds of their libraries as an implementation defined extensions, with a fair number of qualifications. Here's that note, reproduced so that it can be debated more effectively:
The one intentional design change in this paper is in the feature test macros. A new feature test macro will be added, and the existing library feature test macros will be split into two tables: feature test macros available in freestanding environments and feature test macros available in hosted environments.
A freestanding implementation that provides support for this paper shall define the following feature test macro.
Name | Value | Header |
---|---|---|
__cpp_freestanding_library |
201906 | <version> |
Example usage:
#if __cpp_freestanding_library >= 201906 int my_atoi(const char *str); #else #include <cstdlib> inline int my_atoi(const char *str) {return std::atoi(str);} #endif
The __cpp_freestanding_library
macro is useful for detecting the absence of throwing facilities. A user could conditionally use a hand-rolled implementation in freestanding mode or the standard implementation in hosted mode.
The library feature macros have been partitioned into those that must be present in both freestanding and hosted mode, and those that only need to be present in hosted mode. If the implementation provides more than the minimal freestanding subset, then the implementation shall also provide the corresponding feature test macros.
The pre-existing feature macros were not provided on freestanding / hosted boundaries. As a result, a choice has to be made about feature test macros that contain both freestanding and non-freestanding code (e.g. __cpp_lib_chrono
, __cpp_lib_boyer_moore_searcher
, and others). This revision includes feature test macros in freestanding if any of the feature is included in freestanding. Users that need to detect the non-freestanding parts will also need to test against __cpp_freestanding_library
.
The following changes are relative to N4810 from the Post-Kona 2019 mailing.
Add a new subclause [freestanding.membership], under [conventions] and after [objects.within.classes]:Change in [compliance] paragraph 3:?.?.?.? Freestanding membership [freestanding.membership]
The freestanding implementation has several declarations and macro definitions that shall meet the same requirements as for a hosted implementation unless otherwise specified.[ Note: Throwing a standard library provided exception is not observably different from terminate() if the implementation doesn't unwind the stack during exception handling and the user's program contains no catch blocks. -end note]In the associated header synopsis for such declarations and macro definitions, the items shall be followed with a comment that ends with freestanding, as in:#define E2BIG see below // freestandingThe freestanding implementation has several headers that shall meet the same requirements as for a hosted implementation unless otherwise specified.The synopsis for these headers shall start with a comment that ends with freestanding, as in:// freestanding namespace std {
Individual declarations and macro definitions in such a header shall not be followed with a comment that ends with freestanding.Deduction guides for class templates that are implemented (partially or fully) in a freestanding implementation shall be implemented in a freestanding implementation.The containing namespace for each non-namespace declaration that is implemented (partially or fully) in a freestanding implementation shall be implemented in a freestanding implementation.
Instructions to the editor:The supplied version of the header <cstdlib> shall declare at least the functions abort, atexit, at_quick_exit, exit, and quick_exit [support.start.term].The other headers listed in this table shall meet the same requirements as for a hosted implementation.The supplied versions of the header <version> shall meet the requirements specified in [support.limits.general].The other headers listed in this table shall meet the requirements for a freestanding implementation, as specified in the respective header synopsis.
Replace paragraph 3 in [support.limits.general]:??? Header <cstdlib> synopsis [cstdlib.syn]
namespace std { using size_t = see below; // freestanding using div_t = see below; using ldiv_t = see below; using lldiv_t = see below; } #define NULL see below // freestanding #define EXIT_FAILURE see below #define EXIT_SUCCESS see below #define RAND_MAX see below #define MB_CUR_MAX see below namespace std { // Exposition-only function type aliases extern "C" using c-atexit-handler = void(); // exposition only extern "C++" using atexit-handler = void(); // exposition only extern "C" using c-compare-pred = int(const void*, const void*); // exposition only extern "C++" using compare-pred = int(const void*, const void*); // exposition only // [support.start.term], start and termination [[noreturn]] void abort() noexcept; // freestanding int atexit(c-atexit-handler* func) noexcept; // freestanding int atexit(atexit-handler* func) noexcept; // freestanding int at_quick_exit(c-atexit-handler* func) noexcept; // freestanding int at_quick_exit(atexit-handler* func) noexcept; // freestanding [[noreturn]] void exit(int status); // freestanding [[noreturn]] void _Exit(int status) noexcept; [[noreturn]] void quick_exit(int status) noexcept; // freestanding char* getenv(const char* name); int system(const char* string); // [c.malloc], C library memory allocation void* aligned_alloc(size_t alignment, size_t size); void* calloc(size_t nmemb, size_t size); void free(void* ptr); void* malloc(size_t size); void* realloc(void* ptr, size_t size); double atof(const char* nptr); int atoi(const char* nptr); long int atol(const char* nptr); long long int atoll(const char* nptr); double strtod(const char* nptr, char** endptr); float strtof(const char* nptr, char** endptr); long double strtold(const char* nptr, char** endptr); long int strtol(const char* nptr, char** endptr, int base); long long int strtoll(const char* nptr, char** endptr, int base); unsigned long int strtoul(const char* nptr, char** endptr, int base); unsigned long long int strtoull(const char* nptr, char** endptr, int base); // [c.mb.wcs], multibyte / wide string and character conversion functions int mblen(const char* s, size_t n); int mbtowc(wchar_t* pwc, const char* s, size_t n); int wctomb(char* s, wchar_t wchar); size_t mbstowcs(wchar_t* pwcs, const char* s, size_t n); size_t wcstombs(char* s, const wchar_t* pwcs, size_t n); // [alg.c.library], C standard library algorithms void* bsearch(const void* key, const void* base, size_t nmemb, size_t size, c-compare-pred* compar); void* bsearch(const void* key, const void* base, size_t nmemb, size_t size, compare-pred* compar); void qsort(void* base, size_t nmemb, size_t size, c-compare-pred* compar); void qsort(void* base, size_t nmemb, size_t size, compare-pred* compar); // [c.math.rand], low-quality random number generation int rand(); void srand(unsigned int seed); // [c.math.abs], absolute values int abs(int j); long int abs(long int j); long long int abs(long long int j); float abs(float j); double abs(double j); long double abs(long double j); long int labs(long int j); long long int llabs(long long int j); div_t div(int numer, int denom); ldiv_t div(long int numer, long int denom); // see [library.c] lldiv_t div(long long int numer, long long int denom); // see [library.c] ldiv_t ldiv(long int numer, long int denom); lldiv_t lldiv(long long int numer, long long int denom); }
Add a new paragraph to the end of [support.limits.general]:On freestanding and hosted implementations, the macros in Table ??36?? are defined after inclusion of the header <version> or one of the corresponding headers specified in the table.On hosted implementations, the macros in Table ??37?? are defined after inclusion of the header <version> or one of the corresponding headers specified in the table.The presence of the macros in Table ??36?? is implementation defined on freestanding implementations.[Note: Future versions of this International Standard might replace the values of these macros with greater values. -end note]
Split Table 36.A freestanding implementation shall define the __cpp_freestanding_library macro with the value 201906L in the <version> header.
__cpp_lib_atomic_is_always_lock_free
__cpp_lib_atomic_ref
__cpp_lib_bit_cast
__cpp_lib_bool_constant
__cpp_lib_bounded_array_traits
__cpp_lib_byte
__cpp_lib_char8_t
__cpp_lib_concepts
__cpp_lib_hardware_interference_size
__cpp_lib_has_unique_object_representations
__cpp_lib_integral_constant_callable
__cpp_lib_is_aggregate
__cpp_lib_is_constant_evaluated
__cpp_lib_is_final
__cpp_lib_is_invocable
__cpp_lib_is_null_pointer
__cpp_lib_is_swappable
__cpp_lib_launder
__cpp_lib_logical_traits
__cpp_lib_result_of_sfinae
__cpp_lib_transformation_trait_aliases
__cpp_lib_type_trait_variable_templates
__cpp_lib_uncaught_exceptions
__cpp_lib_void_t
__cpp_lib_addressof_constexpr
__cpp_lib_allocator_traits_is_always_equal
__cpp_lib_any
__cpp_lib_apply
__cpp_lib_array_constexpr
__cpp_lib_as_const
__cpp_lib_bind_front
__cpp_lib_boyer_moore_searcher
__cpp_lib_chrono
__cpp_lib_chrono_udls
__cpp_lib_clamp
__cpp_lib_complex_udls
__cpp_lib_constexpr_misc
__cpp_lib_constexpr_swap_algorithms
__cpp_lib_destroying_delete
__cpp_lib_enable_shared_from_this
__cpp_lib_erase_if
__cpp_lib_exchange_function
__cpp_lib_execution
__cpp_lib_filesystem
__cpp_lib_gcd_lcm
__cpp_lib_generic_associative_lookup
__cpp_lib_generic_unordered_lookup
__cpp_lib_generic_unordered_hash_lookup
__cpp_lib_hypot
__cpp_lib_incomplete_container_elements
__cpp_lib_integer_sequence
__cpp_lib_interpolate
__cpp_lib_invoke
__cpp_lib_list_remove_return_type
__cpp_lib_make_from_tuple
__cpp_lib_make_reverse_iterator
__cpp_lib_make_unique
__cpp_lib_map_try_emplace
__cpp_lib_math_special_functions
__cpp_lib_memory_resource
__cpp_lib_node_extract
__cpp_lib_nonmember_container_access
__cpp_lib_not_fn
__cpp_lib_null_iterators
__cpp_lib_optional
__cpp_lib_parallel_algorithm
__cpp_lib_quoted_string_io
__cpp_lib_ranges
__cpp_lib_raw_memory_algorithms
__cpp_lib_robust_nonmodifying_seq_ops
__cpp_lib_sample
__cpp_lib_scoped_lock
__cpp_lib_shared_mutex
__cpp_lib_shared_ptr_arrays
__cpp_lib_shared_ptr_weak_type
__cpp_lib_shared_timed_mutex
__cpp_lib_string_udls
__cpp_lib_string_view
__cpp_lib_three_way_comparison
__cpp_lib_to_chars
__cpp_lib_transparent_operators
__cpp_lib_tuple_element_t
__cpp_lib_tuples_by_type
__cpp_lib_unordered_map_try_emplace
__cpp_lib_variant
Thanks to Brandon Streiff, Joshua Cannon, Phil Hindman, and Irwan Djajadi for reviewing P0829.
Thanks to Odin Holmes for providing feedback and helping publicize P0829.
Thanks to Paul Bendixen for providing feedback while prototyping P0829.
Similar work was done in the C++11 timeframe by Lawrence Crowl and Alberto Ganesh Barbati in N3256.