Заставить gsl::as_span вернуть gsl:: span<const T>?
Принимая следующую функцию, принимая: диапазон с плавающей запятой только для чтения (либо динамического, либо любого статического размера):
template <long N> void foobar(gsl::span<const float, N> x);
Допустим, у меня есть vector<float>
, Передача этого аргумента не работает, но и использование gsl::as_span
:
std::vector<float> v = {1, 2, 3};
foobar(gsl::as_span(v));
Выше не компилируется. По-видимому gsl::as_span()
возвращает gsl::span<float>
, Кроме того, не понимая, почему неявное приведение к gsl::span<const float>
не возможно, есть ли способ заставить gsl::as_span()
вернуть диапазон только для чтения?
1 ответ
Просматривая GSL/span.h на странице github, на которую вы ссылались, я обнаружил следующую перегрузку: as_span
что я верю, это то, что называется здесь:
template <typename Cont>
constexpr auto as_span(Cont& arr) -> std::enable_if_t<
!details::is_span<std::decay_t<Cont>>::value,
span<std::remove_reference_t<decltype(arr.size(), *arr.data())>, dynamic_range>>
{
Expects(arr.size() < PTRDIFF_MAX);
return {arr.data(), narrow_cast<std::ptrdiff_t>(arr.size())};
}
Здесь многое нужно переварить, но, в частности, возвращаемый тип этой функции сводится к span<std::remove_reference<decltype(*arr.data())>, ...>
, Для вашего vector<float>
дает span<float,...>
так как decltype(*arr.data())
является float &
, Я считаю, что следующее должно работать:
const auto & cv = v;
foobar(as_span(cv));
но я не могу проверить это сам, к сожалению. Дайте мне знать, если это работает.
as_span
больше не является частью MS/GSL, вероятно, потому что gsl::span
был недавно согласован с std::span
- который теперь можно использовать с C++20.
Ты можешь использовать std::as_const
чтобы получить контейнер const и создать gsl::span
от этого (или в вашем случае использовать gsl::as_span
в теме).
foobar(gsl::span<const float>(std::as_const(v)));
Обратите внимание, что в зависимости от реализации foobar
шаблонировать его не нужно. Вы также можете просто написать
void foobar(gsl::span<const float> x);
По умолчанию длина пролета равна dynamic_extent
, поэтому допускаются пролеты любой длины. Конечно, во время компиляции у вас не будет доступной длины.