Span lets you use a ranged for loop to iterate over the contents without worrying about exceeding the bounds, which is safer than pointer+size if that's all you'll be doing. C++26 also introduces .at() for span, and the new hardened standard library enforces bounds checking when using operator [] on a span.
You can pass both C arrays and some STL containers (i.e. std::vector, std::array) into a function that takes a span, and the span will get constructed automatically. You have to construct it manually if all you have is a pointer and a length, but I don't know what you'd expect to happen there.
It’s not semantically safe to pass arbitrary vectors into a generic buffer copying function. The T in a vector<T> could have internal pointers or worse things.
Either the objects are simple and trivially copiable, or you need a proper serialization library.
Sure you can use span to generalize slides and iteration, but I don’t think that’s the point of the article.
In comparison to a plain void* and a separate size, it's still an improvement. As others mentioned, void* suffers from the same problem (it might point to a type that is not trivially copyable), except it has more opportunities for mistakes.
In contrast, with span, you can instantiate only to span<uint_8> (or something similar) and you'd still be able to accept other buffer types (such as vector<uint_8>, array<uint_8>, etc.). Alternatively, you can make T bounded to be trivially copyable. You can't do that with void*.
Well if compilation time is an issue, you chose the worst possible language to use. But if you must use C++, you should use the mechanisms that best communicate intent.
It’s this kind of attitude that perpetuates bad compilation time.
Templates have to get parsed and instantiated over and over again. Then you need link time optimization to deduplicate all the redundant copies of the same code.
Untrue. Lots of effort is spent optimizing compilation time at big FAANG companies. And there a lot of established techniques for creating “compiler firewalls” and explicitly instantiating templates once.
But these compilation times optimizations don't significantly undermine the other goals. Given that we're talking about std::span<T>, a pretty small template all things considered, I think practical evidence (e.g. actual cases) of impact is needed.
The problem is not the size of the span template, it’s putting whatever logic into a header file instead of a sealed compilation unit.
In a void* function prototype, whatever network code or gnarly dependency is all shielded behind a compilation unit.
If you make it a template function the compiler will have to (re)process a lot of code.
You could make the interface templatized in a header file and have the actual implementation use void * or char * pointer. That would recover good compiler performance.
I don’t think span provides much if any safety for the implementer of the library function. I’m also not convinced it’s more ergonomic for the caller.