// freestanding-delete
to // freestanding-deleted
bad_optional_access
per LWG's request for consistencystring_view::starts_with
and string_view::ends_with
in terms of freestanding functions// freestanding-deleted
// mostly freestanding
header markerstring_view::contains
All of the added classes are fundamentally compatible with freestanding, except for a few methods that throw (e.g. array::at). We explicitly =delete these undesirable methods.
The main driving factor for these additions is the immense usefulness of these types in practice.
Since we aren’t changing the semantics of any of the classes (except deleted non-critical methods), it is fair to say that all of the (implementer and user) experience gathered as part of hosted applies the same to freestanding.
The only question is, whether these classes are compatible with freestanding. To which the answer is yes! For example, the [Embedded Template Library] offers direct mappings of the std types. Even in kernel-level libraries, like Serenity’s [AK] use a form of these utilities.
Our decision to delete methods we can’t mark as freestanding was made to keep overload resolution the same on freestanding as hosted.
An additional benefit here is, that users of these classes, who might expect to use a throwing method, which was not provided by the implementation, will get a more meaningful error than the method simply missing. This also means we can keep options open for reintroducing the deleted functions into freestanding. (e.g. operator<<(ostream, string_view), should <ostream> be added).
The predecessor to this paper used //freestanding, partial
to mean a class (template) is only required to be partially implemented, in conjunction with //freestanding, omit
meaning a declaration is not in freestanding.
In this paper, we mark not fully freestanding classes templates as // freestanding-partial
, and use P2338's // freestanding-deleted
to mark which pieces of the class should be omitted.
We no longer annotate all the class members, favoring terseness over explicitness.
In this paper, we mark std::visit as freestanding, even though it is theoretically throwing. However, the conditions for std::visit to throw are as follows:
It is possible for a variant to hold no value if an exception is thrown during a type-changing assignment or emplacement.
This means a variant will only throw on visit if a user type throws (library types don’t throw on freestanding). In this case, std::visit throwing isn’t a problem, since the user’s code is already using, and (hopefully) handling exceptions.
This however has the unfortunate side-effect that we need to keep bad_variant_access freestanding.
By getting rid of std::get, we force users to use std::get_if. Since std::get_if returns a pointer, one can only access the value of a variant by dereferencing said pointer, obtaining an lvalue, discarding the value category of the held object. This is unlikely to have an impact on application code, but might impact highly generic library code.
std::forward_like can help in these cases. The value category of the variant can be transferred to the dereferenced pointer returned from set::get_if.
Drafting note: Apply the following change after applying the changes in P2338 "Freestanding Library: Character primitives and the C library".A declaration in a header synopsis is a freestanding item if
- it is followed by a comment that includes freestanding, or
- the header synopsis begins with a comment that includes all freestanding
., or- the header synopsis begins with a comment that includes mostly freestanding and the declaration is not followed by a comment that includes
- freestanding-partial, or
- freestanding-deleted, or
- hosted.
...
A macro is a freestanding item if it is defined in a header synopsis and
- the definition is followed by a comment that includes freestanding, or
- the header synopsis begins with a comment that includes all freestanding
., or- the header synopsis begins with a comment that includes mostly freestanding and the definition is not followed by a comment that includes
- freestanding-partial, or
- freestanding-deleted, or
- hosted.
A class type declaration or class template declaration in a header synopsis that is followed by a comment that includes freestanding-partial is a freestanding item, except that it contains at least one freestanding deleted function.[ Example:template <class T, size_t N> struct array; //freestanding-partial template<class T, size_t N> struct array { constexpr reference operator[](size_type n); constexpr const_reference operator[](size_type n) const; constexpr reference at(size_type n); //freestanding-deleted constexpr const_reference at(size_type n) const; //freestanding-deleted };-end example]
Subclause | Header(s) | |
---|---|---|
[…] | […] | […] |
?.? [optional] | Optional objects | <optional> |
?.? [variant] | Variants | <variant> |
?.? [string.view] | String view classes | <string_view> |
?.? [array] | Class template array |
<array> |
[…] | […] | […] |
Please insert a // mostly freestanding
comment at the beginning of the [optional.syn] synopsis.
// freestanding-partial
comment to the following declaration:
optional
Instructions to the editor:
Please append a // freestanding-deleted
comment to every overload of value
.
Please insert a // mostly freestanding
comment at the beginning of the [variant.syn] synopsis.
Please append a // freestanding-deleted
comment to every get
overload in the synopsis.
Please insert a // mostly freestanding
comment at the beginning of the [string.view.synop] synopsis.
// hosted
comment to the following declaration:
operator<<
// freestanding-partial
comment to the following declaration:
basic_string_view
// freestanding-deleted
to the following functions:
at
copy
substr
compare(size_type pos1, size_type n1, basic_string_view s)
compare(size_type pos1, size_type n1, basic_string_view s, size_type pos2, size_type n2)
compare(size_type pos1, size_type n1, const charT* s)
compare(size_type pos1, size_type n1, const charT* s, size_type n2)
Note that the compare(basic_string_view str) const
and compare(const charT* s) const
overloads are intentionally not freestanding-deleted.
basic_string_view
overload of starts_with
so that it doesn't reference freestanding-deleted methods.
constexpr bool starts_with(basic_string_view x) const noexcept;
Please modify the basic_string_view
overload of ends_with
so that it doesn't reference freestanding-deleted methods.
constexpr bool ends_with(basic_string_view x) const noexcept;
Please insert a // mostly freestanding
comment at the beginning of the [array.syn] synopsis.
Please append a // freestanding-partial
comment to array
// freestanding-deleted
comment to every overload of at
.
#define __cpp_lib_freestanding_array 20XXXXL //also in <array> #define __cpp_lib_freestanding_optional 20XXXXL //also in <optional> #define __cpp_lib_freestanding_string_view 20XXXXL //also in <string_view> #define __cpp_lib_freestanding_variant 20XXXXL //also in <variant>