1

std::span works great on std::vectors, std::arrays or c pointers. However, often the contiguous memory has a different type associated to it such as for example a vector of arrays. I'm trying to use a std::span on vectors of arrays, arrays of arrays, or more generally containers of contiguous data.

For example, if I have a function:

void func(std::span<double> vec){

}

and a vector of array:

std::vector<std::array<double,3>> vec;

I would like to be able to call it like that:

func(vec);

I would like to avoid the std::span<std::array<T,N>> since this is all one block of memory, and I would like to accept std::vector<T>, std::array<T>, and std::vector<std::array<T>> as well. It is possible to do something like that with raw pointer, but then the type is lost and it decays, so I am trying to avoid that.

I could do func(std::span(&vec[0][0], vec.size()*3)), but I am wondering if there is something better.

2
  • Personally I would just take the container as is like template <typename Container2D> func(Container2D cont) and if you want to you can use concepts to enforce the interface you want. Commented Nov 3, 2024 at 1:07
  • @NathanOliver: Though in that case you probably want to receive by reference or const reference; std::span is cheap to pass, actual containers would involve copies if not received by reference. Commented Nov 3, 2024 at 14:34

1 Answer 1

2

I could do func(std::span(&vec[0][0], vec.size()*3)), but I am wondering if there is something better.

That is going to end in undefined behavior. It is not possible to access beyond a single std::array element of the vector, even if they are laid-out contiguously.

There are rules in the standard currently that would permit a compiler to optimize under the assumption that it is impossible to go out of bounds of the individual std::array object from a pointer to one of the std::array's elements, even though I am not aware of any compiler currently doing so.

There have been proposals to change the standard to permit what you want, but I am not aware of any progress in that direction.

This is not specific to std::span either. With a raw pointer you have the same problem. Pointer arithmetic is only ever defined in a single array, not across array objects.

Instead of a vector of arrays of doubles, just use a vector of doubles wrapped in a class with member functions and operator overloads that handle the correct 2d-indexing for you. Then passing arbitrary sections as std::span is trivial and has defined behavior.

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you for your answer. I tried on clang and it works, which does not mean it is correct, as you said.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.