Bug 117541

Summary: vector::insert_range should not use ranges::copy
Product: gcc Reporter: 康桓瑋 <hewillk>
Component: libstdc++Assignee: Not yet assigned to anyone <unassigned>
Status: NEW ---    
Severity: normal CC: daniel.kruegler, hubicka, webrown.cpp
Priority: P3    
Version: 15.0   
Target Milestone: ---   
Host: Target:
Build: Known to work:
Known to fail: Last reconfirmed: 2024-11-13 00:00:00
Bug Depends on:    
Bug Blocks: 118130, 111055    

Description 康桓瑋 2024-11-12 02:10:56 UTC
Unlike vector::assign_range which requires assignable_from<T&, ranges​::​range_reference_t<R>> is true, this means that ranges::copy is not necessarily well-formed for vector::insert_range:

#include <vector>

struct Int {
  void operator=(int) = delete;
  Int(int);
};

int main() {
  std::vector<Int> v;
  v.insert_range(v.begin(), std::vector{42});
}

https://godbolt.org/z/jo3vjjo5b
Comment 1 Jonathan Wakely 2024-11-12 10:35:08 UTC
ranges::copy performs exactly the same operations as vector::insert(p, i, j) does, which fails the same way for libstdc++ and libc++:

  std::vector<Int> v;
  std::vector<int> vi{42};
  v.insert(v.begin(), vi.begin(), vi.end());

So this seems like a pre-existing issue. Arguably, it's a standard defect. Why should be construct new elements when we already have some in the right locations?
Comment 2 Jonathan Wakely 2024-11-12 10:53:02 UTC
MSVC creates a hole in the middle of the vector, destroying the elements that were there previously, then fills the hole using uninitialized_copy.