https://gcc.gnu.org/bugzilla/show_bug.cgi?id=103919

            Bug ID: 103919
           Summary: The basic_string(const T&, size_type, size_type)
                    constructor is overconstrained
           Product: gcc
           Version: 12.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: libstdc++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: barry.revzin at gmail dot com
  Target Milestone: ---

>From StackOverflow (https://stackoverflow.com/q/70591571/2069064), with a clear
description of the problem.

This constructor:

      template<typename _Tp, typename = _If_sv<_Tp, void>>
        _GLIBCXX20_CONSTEXPR
        basic_string(const _Tp& __t, size_type __pos, size_type __n,
                     const _Alloc& __a = _Alloc())
        : basic_string(_S_to_string_view(__t).substr(__pos, __n), __a) { }

is constrained using:

      template<typename _Tp, typename _Res>
        using _If_sv = enable_if_t<
          __and_<is_convertible<const _Tp&, __sv_type>,
                 __not_<is_convertible<const _Tp*, const basic_string*>>,
                 __not_<is_convertible<const _Tp&, const _CharT*>>>::value,
          _Res>;

But while the (const T&, const Allocator&) constructor does need that
additional requirement that const T& isn't convertible to const charT* (and is
specified to have this check), the original constructor I linked to does not -
since there wouldn't be any ambiguity there
(http://eel.is/c++draft/string.cons#5).

As such, a construction like:

    string s("some string to test", 2, 3);

Instead of converting the literal to a string_view and doing a substr, instead
invokes this constructor:

      _GLIBCXX20_CONSTEXPR
      basic_string(const basic_string& __str, size_type __pos,
                   const _Alloc& __a = _Alloc())

Which requires (unnecessarily) allocating a new string.

Reply via email to