Должен ли я вернуть gsl :: span & lt; const T & gt; вместо const std :: vector & lt; T & gt; & amp;

У меня есть класс с std :: vector<ИНТ> member и функция-член, возвращающая константную ссылку на этот вектор.

class demo {
public:
//...

const std::vector<int> & test() const {
return iv;
}

private:

std::vector<int> iv;
};

Я планирую изменить тип члена на другой массив, такой как тип контейнера, с достаточной функциональностью и меньшим объемом памяти (например, std :: экспериментальный :: dynarray, std :: unique_ptr<ИНТ []>). Поэтому я подумал, что было бы неплохо не возвращать реальный контейнер как константную ссылку, а возвращать представление элементов в виде gsl :: span<const int>,

class demo {
public:
//...

gsl::span<const int> test() const {
return iv;
}

private:

std::vector<int> iv;
};

Но это нарушает код, который работал с константным вектором<ИНТ>& потому что два экземпляра span одного и того же неизмененного вектора не могут быть использованы для итерации по элементам:

demo d;

std::cout << (d.test().begin() == d.test().begin()) << "\n";
std::cout << (d.test().end() == d.test().end()) << "\n";

for( auto it = d.test().begin(), end = d.test().end(); it != end; ++it )
std::cout << *it << "\n";

Это печатает 0 0 и затем терпит крах, потому что проверить это! = End никогда не терпит неудачу.
Конечно, диапазон, основанный на цикле, работает, но этот цикл действителен и поэтому должен также работать как положено.
Я ожидал, что все диапазоны из одного и того же диапазона одного и того же контейнера равны, так что итераторы любого из этих диапазонов сопоставимы (контейнер, конечно, не изменен). Конечно, есть веская причина, почему это не так.

Поэтому мой вопрос заключается в том, каков наилучший способ вернуть такое представление элементам массива, таким как контейнер, тип которых не должен быть виден вызывающей стороне.

6

Решение

Ты используешь iterator временный, так что ваш iterator стать инвалидом сразу после воздействия.

Вы можете использовать следующее:

auto&& view = d.test();
for (auto it = view.begin(), end = view.end(); it != end; ++it) {
std::cout << *it << "\n";
}
2

Другие решения

Так что ответ НЕТ, потому что это нарушает код, который был действителен раньше.

0