Date: Tue, 9 Dec 2025 10:14:22 +0100
Isn't it enough, if the for loop checks for the last element instead of one beyond?
This would work with all containers with bidirectional iterators. For forward_list there is not even a push_back() function.
#include <vector>
struct mytype {
std::vector<int> vec;
// in real code it is complex iterator
// where vector iterator only part of it
using iterator = std::vector<int>::iterator;
void append(iterator b, iterator e) {
--e; // INSERT
for (; b != e; ++b) { // ASSERTION FAILURE, COMPARING b and e after push_back
// again, in real code it complex operation with inserting in my container
vec.push_back(*b);
}
vec.push_back(*b); // INSERT
}
iterator begin() {
return vec.begin();
}
iterator end() {
return vec.end();
}
};
int main() {
mytype x;
x.vec = {1, 2, 3, 4};
x.vec.reserve(100);
x.append(x.begin(), x.end());
}
-----Ursprüngliche Nachricht-----
Von:Nikl Kelbon via Std-Proposals <std-proposals_at_[hidden]>
Gesendet:Di 09.12.2025 05:19
Betreff:Re: [std-proposals] vector::push_back must not invalidate past-the-end iterator
An:std-proposals_at_[hidden];
CC:Nikl Kelbon <kelbonage_at_[hidden]>;
Im glad you now asking for a motivation and not asking "what is past the end iterator" or smth what was discussed before
In real code i created my container template, so its iterator combines several iterators of its parts. std::vector was one of those parts
Then i wrote append(iterator, iterator) and my code sures it is completely right, no reallocation etc etc.
But msvc stl implementation find a way to assert it (by storing all .end() iterators in global map under mutex and invalidate them on each push_back)
I dont know any other way to code it. Its impossible. THERE ARE NO OTHER WAY!
Code:
#include <vector>
struct mytype {
std::vector<int> vec;
// in real code it is complex iterator
// where vector iterator only part of it
using iterator = std::vector<int>::iterator;
void append(iterator b, iterator e) {
for (; b != e; ++b) { // ASSERTION FAILURE, COMPARING b and e after push_back
// again, in real code it complex operation with inserting in my container
vec.push_back(*b);
}
}
iterator begin() {
return vec.begin();
}
iterator end() {
return vec.end();
}
};
int main() {
mytype x;
x.vec = {1, 2, 3, 4};
x.vec.reserve(100);
x.append(x.begin(), x.end());
}
https://godbolt.org/z/cjfT9vran
вт, 9 дек. 2025 г. в 07:18, Jason McKesson via Std-Proposals <std-proposals_at_[hidden] <mailto:std-proposals_at_[hidden]> >:
On Mon, Dec 8, 2025 at 1:56 PM Nikl Kelbon via Std-Proposals
<std-proposals_at_[hidden] <mailto:std-proposals_at_[hidden]> > wrote:
>
> Thats what standard exists for. Standard decides what is ub and what is not ub. How its even may be argument "its ub" in discussion about changing standard?
Because your reasoning for why this change is needed is that many
users do it regardless of the fact that it's UB, so it makes sense to
change it. That is, your proposal is predicated on the idea that this
is common code, and therefore if it isn't common code, then it has no
motivation.
So, what evidence can you provide that people believe that end
iterators should work this way? The fact that it can be implemented is
not, by itself, sufficient justification for changing the standard.
--
Std-Proposals mailing list
Std-Proposals_at_[hidden] <mailto:Std-Proposals_at_[hidden]>
https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
--
Std-Proposals mailing list
Std-Proposals_at_[hidden]
https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
Received on 2025-12-09 09:29:06
