3942. Inconsistent use of const char_type& in standard specializations of std::char_traits

Section: 27.2.4 [char.traits.specializations] Status: New Submitter: Jiang An Opened: 2023-05-27 Last modified: 2023-06-01

Priority: 3

View all other issues in [char.traits.specializations].

View all issues with New status.

Discussion:

In the standard specializations of std::char_traits (std::char_traits<char> etc.), there are a few member functions take a single character via a const char_type& parameter, while other functions take a single character by value.

In C++98, there were more functions taking const char_type&. N2349 changed this in C++11 by making some, but not all of them take char_type. It is unclear whether the inconsistency is intended, and it seems better for these standard specializations to take a character by value.

However, libstdc++ hasn't implemented the signature changes, perhaps due to ABI concerns. So it might be better to loose the restrictions for the purpose of standardization.

[2023-06-01; Reflector poll]

Set priority to 3 after reflector poll.

Proposed resolution:

This wording is relative to N4950.

[Drafting Note: Two mutually exclusive options are prepared, depicted below by Option A and Option B, respectively.]

Option A: This assumes that "by-value" arguments are intended.

  1. Modify the class template char_traits specialization synopses in 27.2.4.2 [char.traits.specializations.char], 27.2.4.3 [char.traits.specializations.char8.t], 27.2.4.4 [char.traits.specializations.char16.t], 27.2.4.5 [char.traits.specializations.char32.t], and 27.2.4.6 [char.traits.specializations.wchar.t] as indicated:

    […]
        static constexpr void assign(char_type& c1, const char_type& c2) noexcept;
    […]
        static constexpr const char_type* find(const char_type* s, size_t n,
                                               const char_type& a);
    […]
    

Option B: This assumes that implementation-freedom to keep ABI stability is intended.

[Drafting Note: It is intended to keep the assign(s, n, a) taking the character by value, because the argument may be a character in [s, s + n).]

  1. Add a paragraph at the end of 27.2.4.1 [char.traits.specializations.general] as indicated:

    -?- For each occurrence of the placeholder const-char-t in the synopsis of each of these specializations, it is unspecified whether it denotes char_type or const char_type&. Likewise, for each occurrence of the placeholder const-int-t in the synopsis of each of these specializations, it is unspecified whether it denotes int_type or const int_type&

  2. Modify the class template char_traits specialization synopses in 27.2.4.2 [char.traits.specializations.char], 27.2.4.3 [char.traits.specializations.char8.t], 27.2.4.4 [char.traits.specializations.char16.t], 27.2.4.5 [char.traits.specializations.char32.t], and 27.2.4.6 [char.traits.specializations.wchar.t] as indicated:

    […]
        static constexpr void assign(char_type& c1, const char_type&const-char-t c2) noexcept;
        static constexpr bool eq(char_typeconst-char-t c1, char_typeconst-char-t c2) noexcept;
        static constexpr bool lt(char_typeconst-char-t c1, char_typeconst-char-t c2) noexcept;
    […]
        static constexpr const char_type* find(const char_type* s, size_t n,
                                               const char_type&const-char-t a);
    […]
        static constexpr int_type not_eof(int_typeconst-int-t c) noexcept;
        static constexpr char_type to_char_type(int_typeconst-int-t c) noexcept;
        static constexpr int_type to_int_type(char_typeconst-char-t c) noexcept;
        static constexpr bool eq_int_type(int_typeconst-int-t c1, int_typeconst-int-t c2) noexcept;
    […]