Заставить 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, поэтому допускаются пролеты любой длины. Конечно, во время компиляции у вас не будет доступной длины.

Другие вопросы по тегам