5 ms·
Span will increase compilation time for no useful reason. It’s not any safer at the call site.
by drivebyhooting 4mo ago
Span will increase compilation time for no useful reason.
It’s not any safer at the call site.
- throwaway27448 4mo agoWell 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.
- drivebyhooting 4mo agoIt’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.
- fluffybucktsnek 4mo agoIf youif you are using C++, your last concern will be compilation times. By this point, just use C.
- drivebyhooting 4mo agoUntrue. 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.
- fluffybucktsnek 4mo agoBut 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.
- drivebyhooting 4mo agoThe 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.
- throwaway27448 4mo agoIt is, however, more readable and maintainable.
- fluffybucktsnek 4mo agoYou don't have to make function templated to use span. Given: void DoSomething(void* p, size_t numBytes); Presuming p to mean a buffer of bytes, the direct declaration equivalent using span would be: void DoSomething(std::span<std::uint_8> /* or std::span<char> */ p); No templated logic in header files necessary. The only template instantion is std:span, which, in theory, should already be used in most files. The author argues this still makes the code more complex, because of the need of reinterpret_cast, but does it actually? std::span provides multiple ways of safely accessing data. For one, it provides an contiguous iterator, so you get access to the algorithms library basically for free. Second, you get safer accessors to the data inside, such as at, and even [] can be protected through contracts. Finally, even if you don't care about/can use these features, tying the pointer and length together reduces chances for variable confusion.
- pjmlp 4mo agoNo they don't, modules exist, as do external template libraries.
- ndiddy 4mo agoSpan 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.
- drivebyhooting 4mo agoThe caller still needs to construct the span correctly.
- ndiddy 4mo agoYou 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.
- drivebyhooting 4mo agoIt’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.
- fluffybucktsnek 4mo agoIn 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*.