编写接受可变跨度作为不可变跨度的模板函数

Write template function that accepts mutable span as an immutable span

本文关键字:不可变 函数      更新时间:2023-10-16

gsl::span是一段内存的视图。

foo 是一个模板函数,可以接受可变范围和不可变范围。

我希望 foo 中的代码始终只能对块内存进行不可变的访问。

#include <gsl/gsl>  // gsl-lite
template <typename T>
void foo(gsl::span<const T> x) {}
int main() {
    int arr[] = {0, 1, 2, 3, 4};
    auto s1 = gsl::span<int>(arr);
    foo(s1);
}

这不起作用,因为在模板实例化期间没有类型转换。

如果我写以下内容:

template <typename T>
void foo(gsl::span<T> x) {}

foo内,x可以是一个可变的跨度。

此用例的正确修复方法是什么?

gsl::span<const T>具有接受gsl::span<T>的构造函数。所以你"只是"有一个模板推导的问题。

您可以通过多种方式解决问题:

  • 在调用站点明确:

    • 呼叫foo<int>(arr)
    • 或致电foo(gsl::span<const int>(arr))
  • 写入重载:

    template <typename T>
    void foo(gsl::span<const T> arr) { /* Your implementation */ }
    template <typename T>
    void foo(gsl::span<T> arr) { foo(gsl::span<const T>(arr)); }
    
  • 编写帮助程序函数,使其在调用站点不太明确,例如:

    template <typename T>
    span<const T> as_immutable_view(span<T> s) { return s; }
    

    然后呼叫foo(as_immutable_view(arr))

如何从

参数中制作变量的常量版本?

template <typename T>
void foo(gsl::span<T> x_raw)
{
   gsl::span<const T> x { x_raw }; // add const if not already present
   // use x in the code
}