std::vector
и почти все другие контейнеры имеют очень удобный способ проверки границ: at()
. У std::span
этого явно нет.
- Почему?
- Есть ли замена? Кроме развертывания собственного
at()
?
std::vector
и почти все другие контейнеры имеют очень удобный способ проверки границ: at()
. У std::span
этого явно нет.
at()
?Довольно коряво, но примерно так:
template<class Container>
auto& at(Container&& c, std::size_t pos){
if(pos >= c.size())
throw std::out_of_range("out of bounds");
return c[pos];
}
template<class Iterator, class Container>
auto& at(Container&& c, Iterator&& it){
if(std::distance(c.begin(), it) >= c.size())
throw std::out_of_range("out of bounds");
return *it;
}
Container&&
должен быть прямой ссылкой, см. it-solves/3582313#3582313">здесь, поэтому вам не нужно переопределять его для каждого константного/неконстантного типа ecc ecc, на самом деле const std::vector<int> v{1,2,3}; std::cout << at(v, v.end());
должно работать нормально
- person Alberto Sinigaglia; 02.08.2020
auto&
) на что-то, что через мгновение исчезнет.
- person Evg; 02.08.2020
std::vector::operator[]
делает то же самое. Нет?
- person Ayxan Haqverdili; 02.08.2020
std::cout << std::vector<std::string>{"a","b","c"}[2];
или std::vector<std::string>{"a","b","c"}.at(2)
, так что я думаю, что это не так уж важно
- person Alberto Sinigaglia; 02.08.2020
std::distance(c.begin(), it) >= c.size()
, а не it == c.end()
? std::distance
может занять линейное время, тогда как разыменование итератора — постоянное время.
- person Evg; 02.08.2020
c.end()+10
, с ==
вы не получите реальную проверку привязки
- person Alberto Sinigaglia; 02.08.2020
c.end() + 10
- это всегда неопределенное поведение, даже для std::vector
, и то, что происходит после UB, не имеет значения.
- person Evg; 02.08.2020
at()
получит size_t
, поэтому, вероятно, версия с итерацией не будет использоваться.
- person Alberto Sinigaglia; 02.08.2020
span
содержит заразный контейнер памяти, который будет иметь постоянную оценку расстояния, поскольку вы, вероятно, можете просто использовать operator-
между двумя итераторами.
- person Alberto Sinigaglia; 02.08.2020
std::get()
делает нечто иное. Разве бесплатный at()
не должен делать то же самое? Я просто спрашиваю.
- person Evg; 02.08.2020
operator-
выглядит как хорошая альтернатива. Тогда этот (общий) код не будет компилироваться для итераторов, которые не поддерживают постоянное время std::distance
, и это хорошо.
- person Evg; 02.08.2020
operator-
. Однако, поскольку это предназначено только для отладки, это не должно иметь значения в любом случае.
- person Ayxan Haqverdili; 02.08.2020
-D_GLIBCXX_DEBUG
сообщает о нарушении утверждения для доступа за пределы []
на std::span
: Assertion '__idx < size()' failed.
.
- person Evg; 02.08.2020
статья, которая представила span в стандартная библиотека говорит:
Проверка диапазона и безопасность границ
Все обращения к данным, инкапсулированным в диапазоне, концептуально проверяются по диапазону, чтобы гарантировать, что они остаются в пределах диапазона. То, что на самом деле происходит в результате несоблюдения ограничений boundssafety во время выполнения, — это неопределенное поведение.
То есть операции имеют узкие контракты, дающие свободу исполнителю.
Если ваша стандартная библиотека не позволяет вам контролировать поведение с соответствующей степенью детализации. gsl-lite предлагает замену с настраиваемым поведением при нарушении контракта. Microsoft GSL ранее можно было настроить, но теперь всегда прекращается при нарушении контракта, обсуждалось здесь (что может быть именно тем, что вам нужно).
std::vector::at
, я знаю, что он будет проверять границы, использую ли я GCC, Clang, MSVC или что-то еще.
- person Ayxan Haqverdili; 02.08.2020
operator[]
, и в качестве альтернативы у нас была отдельная функция более широкого контракта (at
), и мне было интересно, почему это не было добавлено в span
.
- person Ayxan Haqverdili; 02.08.2020
at
для наших контейнеров, таких как vector и basic_string
- person Ayxan Haqverdili; 02.08.2020
at
выдает исключение, когда индекс выходит за границы. Выход за границы в span
рассматривается как нарушение контракта, и поведение не контролируется в коде, поскольку вы можете настроить отсутствие действий, создание исключения или завершение.
- person Yongwei Wu; 08.03.2021
at()
и подобные интерфейсы на основе исключений были заблуждением, которое служит в первую очередь для сокрытия логических ошибок при значительных накладных расходах. - person Ext3h   schedule 02.08.2020at()
отлично подходит для отладки - person Ayxan Haqverdili   schedule 02.08.2020