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.