https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110945
Jonathan Wakely <redi at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- Ever confirmed|0 |1 Last reconfirmed| |2023-08-08 Status|UNCONFIRMED |NEW --- Comment #6 from Jonathan Wakely <redi at gcc dot gnu.org> --- (In reply to Jonathan Wakely from comment #4) > because string::assign has to handle possible aliasing. It's valid to do > things like str.assign(str.data()+1, str.data()+2). Even more problematic is something like: str.assign(make_move_iterator(str.begin()), make_move_iterator(str.begin()+n)); or something similar with a counted_iterator wrapped in a common_iterator. We can't rely on the iterators not being (convertible to) const char* to decide that they don't alias the existing content, because arbitrary iterator types could still alias the characters in the string. It might be better to not use replace(begin(), end(), first, last) for assign(first, last) though, because when we're replacing the entire string we don't need the code that decides if we need to shuffle the existing content around. And _M_replace_dispatch creates a new copy anyway: _M_replace_dispatch(const_iterator __i1, const_iterator __i2, _InputIterator __k1, _InputIterator __k2, std::__false_type) { // _GLIBCXX_RESOLVE_LIB_DEFECTS // 2788. unintentionally require a default constructible allocator const basic_string __s(__k1, __k2, this->get_allocator()); const size_type __n1 = __i2 - __i1; return _M_replace(__i1 - begin(), __n1, __s._M_data(), __s.size()); } So maybe assign(InputIterator, InputIterator) could just do: basic_string& assign(_InputIterator __first, _InputIterator __last) { return assign(basic_string(__first, __last)); } We know _M_replace_dispatch will make a copy anyway.