c++c++20dangling-pointerstd-span

How to pass an rvalue std::vector to a function accepting std::span


Let's say I have a function accepting an std::span<int>, and I want to call it with an rvalue of an std::vector<int>:

void foo(std::span<int> s);

std::vector<int> make_vector();

int main() {  
  foo(make_vector());
}

This will give me an error:

Candidate function not viable: no known conversion from std::vector<int> to std::span<int> for 1st argument

Indeed, generally we don't want to convert a soon-to-be-expired vector to a span, which will become dangling the moment the vector is gone. But here we clearly do not do anything illegal.

Sure, I can store the vector in a temporary variable, and this will work:

  auto v = make_vector();
  foo(v);

But this is more verbose and is no longer a one-liner, which is inconvenient in some contexts.

Is there a way to tell the compiler that that's ok to do the conversion in this particular case?


Solution

  • If you were not planning on modifying the contents of the span from within the function (which is usually true), you can convey your intention by explicitly qualifying the span::element_type as const:

    void foo(std::span<const int> s);
    

    In this case, it is okay to construct a span<const int> from an rvalue vector<int>, even though it is not a borrowed_range. See overload (7) of the constructor of std::span:

    1. Constructs a span that is a view over the range range; ...
    • This overload participates in overload resolution only if
      • ...
      • either R satisfies borrowed_range or std::is_const_v<element_type> is true