3857. basic_string_view should allow explicit conversion when only traits vary

Section: 27.3.3.2 [string.view.cons] Status: C++23 Submitter: Casey Carter Opened: 2023-01-10 Last modified: 2023-11-22

Priority: Not Prioritized

View all other issues in [string.view.cons].

View all issues with C++23 status.

Discussion:

basic_string_view has a constructor that converts appropriate contiguous ranges to basic_string_view. This constructor accepts an argument by forwarding reference (R&&), and has several constraints including that specified in 27.3.3.2 [string.view.cons]/12.6:

if the qualified-id remove_reference_t<R>::traits_type is valid and denotes a type,  is_same_v<remove_reference_t<R>::traits_type, traits> is true.

This constraint prevents conversions from basic_string_view<C, T1> and basic_string<C, T1, A>  to basic_string_view<C, T2>. Preventing such seemingly semantic-affecting conversions from happening implicitly was a good idea, but since the constructor was changed to be explicit it no longer seems necessary to forbid these conversions. If a user wants to convert a basic_string_view<C, T2> to  basic_string_view<C, T1> with static_cast<basic_string_view<C, T1>>(meow) instead of by writing out basic_string_view<C, T1>{meow.data(), meow.size()} that seems fine to me. Indeed, if we think conversions like this are so terribly dangerous we probably shouldn't be performing them ourselves in 28.5.8.1 [format.arg]/9 and 28.5.8.1 [format.arg]/10.

[2023-02-01; Reflector poll]

Set status to Tentatively Ready after six votes in favour during reflector poll.

[2023-02-13 Approved at February 2023 meeting in Issaquah. Status changed: Voting → WP.]

Proposed resolution:

This wording is relative to N4917.

  1. Modify 27.3.3.2 [string.view.cons] as indicated:

    template<class R>
      constexpr explicit basic_string_view(R&& r);
    

    -11- Let d be an lvalue of type remove_cvref_t<R>.

    -12- Constraints:

    1. (12.1) — remove_cvref_t<R> is not the same type as basic_string_view,

    2. (12.2) — R models ranges::contiguous_range and ranges::sized_range,

    3. (12.3) — is_same_v<ranges::range_value_t<R>, charT> is true,

    4. (12.4) — is_convertible_v<R, const charT*> is false, and

    5. (12.5) — d.operator ::std::basic_string_view<charT, traits>() is not a valid expression, and.

    6. (12.6) — if the qualified-id remove_reference_t<R>::traits_type is valid and denotes a type, is_same_v<remove_reference_t<R>::traits_type, traits> is true.