3

给定以下函数,采用:只读浮点跨度(动态或任何静态大小):

template <long N> void foobar(gsl::span<const float, N> x);

假设我有一个vector<float>. 将其作为参数传递是行不通的,但 using 也不行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()返回只读跨度?

4

2 回答 2

1

在您链接到的 github 页面上浏览 GSL/span.h,我发现以下重载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));

但不幸的是,我自己无法测试。让我知道这个是否奏效。

于 2016-06-09T14:33:13.917 回答
1

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,因此可以接受任何长度的跨度。当然,您在编译期间不会有可用的长度。

于 2020-03-01T14:45:33.943 回答