R zu
R zu

Reputation: 2074

Write template function that accepts mutable span as an immutable span

A gsl::span is view of a piece of memory.

foo is a template function that can accept either a mutable span and an immutable span.

I want the code within foo to always only have immutable access to the piece memory.

#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);
}

This doesn't work because no type conversion during template instantiation.

If I write the following instead:

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

Within foo, x can be a mutable span.

What is the correct fix for this use case?

Upvotes: 0

Views: 792

Answers (2)

JDługosz
JDługosz

Reputation: 5652

How about just making a const version of the variable out of the parameter?

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
}

Upvotes: 1

Jarod42
Jarod42

Reputation: 217593

gsl::span<const T> has constructor accepting gsl::span<T>. So you "just" have an issue of template deduction.

You have several ways to workaround your issue:

  • Be explicit at call site:

    • call foo<int>(arr)
    • or call foo(gsl::span<const int>(arr))
  • Write overloads:

    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)); }
    
  • Write helper functions to be less explicit at call site, for example:

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

    and then call foo(as_immutable_view(arr))

Upvotes: 2

Related Questions