#StackBounty: #c++ #language-lawyer #c++20 #placement-new Calling `std::vector<A>::data()` on `A` with const or reference fields,…

Bounty: 50

This is a followup on the answers for placement new on a class with reference field.

Calling std::vector<A>::data() on type A that has reference or const fields, returns a pointer to objects that may be changed through the original vector by placement new, which causes a const or reference field of an original object to be replaced, while still being managed by another pointer, returned via the call to data().

For example:

struct A {
    const int i = 0;
};

int main() {
    std::vector<A> vec = {{1}, {2}};
    auto ptr = vec.data();
    std::cout << ptr[1].i << std::endl; // 2
    vec.pop_back();
    vec.push_back({3}); // placement new, inside
    std::cout << ptr[1].i << std::endl; // 3
}

C++17 tried to resolve such issues by introducing std::launder but it was later agreed that while std::launder may solve other issues, it doesn’t really solve the problem for above use case as noted in NB US042.

Some questions – for C++ versions prior to C++20:

  • Since NB US042 was accepted as a change for C++20 spec, but not marked as a DR – would it be advised, according to the spec only, to avoid the use of std::vector<A>::data() on a type A that has reference or const fields as in above example?

  • Or, the wording of the spec for std::vector<>::data() covers that, making it legal and leaving the implementability question to the library implementers?

  • If it is the latter, what can the library do to make it legal?

  • If it can’t really do anything useful to make it legal, is it UB before C++20?

  • If it is UB before C++20, why wasn’t this change considered to be a candidate for a DR, same as p0593r6? Most probably compilers do the right thing anyway, why not mandate that retroactively?


Get this bounty!!!

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.