Reputation: 1583
Given the following function, taking: a read-only float span (of either dynamic or any static size):
template <long N> void foobar(gsl::span<const float, N> x);
Let's say I have a vector<float>
. Passing that as an argument doesn't work, but neither does using gsl::as_span
:
std::vector<float> v = {1, 2, 3};
foobar(gsl::as_span(v));
The above does not compile. Apparently gsl::as_span()
returns a gsl::span<float>
. Besides not understanding why implicit cast to gsl::span<const float>
isn't possible, is there a way to force gsl::as_span()
to return a read-only span?
Upvotes: 3
Views: 2040
Reputation: 16771
as_span
is not part of MS/GSL any more, probably because gsl::span
was lately aligned to std::span
- which you could now use with C++20.
You can use std::as_const
to get a const container and create a gsl::span
from that (or in your case to use gsl::as_span
on it).
foobar(gsl::span<const float>(std::as_const(v)));
Please note that depending on the implementation of foobar
it is not necessary to template it. You could also just write
void foobar(gsl::span<const float> x);
Per default the length of the span is dynamic_extent
, so spans of any length would be accepted. Of course you would not have the length available during compile time.
Upvotes: 1
Reputation: 10780
Poking around GSL/span.h on the github page you linked to, I found the following overload of as_span
that I believe is the one being called here:
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())};
}
There's lots to digest here, but in particular the return type of this function boils down to span<std::remove_reference<decltype(*arr.data())>, ...>
. For your given vector<float>
gives span<float,...>
because decltype(*arr.data())
is float &
. I believe the following should work:
const auto & cv = v;
foobar(as_span(cv));
but can't test it myself unfortunately. Let me know if this works.
Upvotes: 1