// freestanding-delete to // freestanding-deletedbad_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::containsAll 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:
optionalInstructions 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:
atcopysubstrcompare(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>