У меня есть ситуация, когда я хочу скопировать данные из std::span в std::vector, используя assign. В определенных ситуациях диапазон может находиться на самом целевом векторе.
В cppref указано, что (выделено мной)
Заменяет содержимое копиями содержимого диапазона [
first,last). Поведение не определено, если любой из аргументов является итератором в*this.
Это определенное поведение?
std::vector<char> buffer;
size_t parse(std::span<char>);
void consume(std::span<char> data)
{
// if there was some left over data in our buffer, append new data to buffer
// and use the buffer as source for parsing
if (!buffer.empty())
{
buffer.insert(buffer.end(), data.begin(), data.end());
data = buffer;
}
// Parse data, may result in some left-over data for subsequent call
size_t leftOver = parse(data);
// Store non-consumed data in buffer
// Note: data may be a view on buffer here!
buffer.assign(data.begin() + leftOver, data.end()); // UB?
}





Это УБ.
Смысл этого правила в том, что vector может перераспределить буфер и/или переместить элементы перед разыменованием вашего итератора.
Это одинаково проблематично для vector итераторов, указателей на него, span итераторов и т. д.
@king_nak не просто перераспределения, а порядок копирования элементов. Вы можете написать в элемент, из которого позже будете читать.
@Калет, я понимаю. Таким образом, это ограничение дает разработчику больше свободы.
Я почти уверен, что это будет неопределенное поведение. Термин «итератор в контейнер» не определен стандартом, но в других местах говорится о конкретных итераторах, относящихся к элементу контейнера. Диапазон, указанный data, действительно относится к элементам buffer в том случае, если вас это беспокоит.
Да, я предполагал, что будет именно так. В C++ref используется термин «итератор в `*this*», но это не стандарт...
@king_nak В стандарте используется примерно то же самое «a.assign(i, j) Предварительные условия: ... Ни i, ни j не являются итераторами в a».
Я понял идею в целом. Однако вектор должен иметь достаточную емкость (и размер), поскольку итераторы находятся внутри себя. Я не вижу причины, по которой хранилище должно быть перераспределено в этом случае. Но я признаю, что это так