4 ms·
This is also C++20’s calling card. It has `std::span`.
by BenFrantzDale 4y ago
This is also C++20’s calling card. It has `std::span`.
- int_19h 4y agoSpans/slices are getting incredibly common in as a fundamental building block in modern (or modernized PLs). C# also has Span<T>, Go and Rust both have slices etc. We are at the point where they should be standardized on ABI level, IMO, before things get too messy compatibility-wise.
- flohofwoe 4y agoFor a C API, a slice would be a simple { void*, size_t } or { void*, void* } struct, but I guess for memory managed languages this isn't enough information to pin the underlying data into memory (for instance a reference to the underlying 'object' - don't know how such language-specific details could ever be expressed in a 'standard ABI').
- int_19h 4y agoOh, it's simple enough, even with managed languages in the picture - it just needs to be decided once, and then everybody uses it. The problem is that many existing ABIs don't optimize for small structs as function arguments particularly well, so just bolting it on like that can mean poor performance compared to old-school separate arguments for pointer and length. You want a hard guarantee that something like foo(slice1, slice2) will be passed entirely in the registers, not as two pointers-to-stack.
- pjmlp 4y agoEnter COM and WinRT, if only the tooling wasn't so stuck in the stone age of early 2000's.
- tialaramex 4y agoThere are interesting differences in these types worth thinking about if you're imagining try to standardize them somehow. C++ std::span pulls double duty, one flavour of std::span, the one you might see more often, is like Rust's slice type [T] in that it consists of zero or more values of some type T. The other though is more like Rust's array type [T; N] where the size N of the span is actually part of the type itself. Rust's slice is specifically that [T] type, the type system doesn't see any more difference between a [u32] with 1000 entries and a [u32] with 0 entries than it would between a string with "DOG" in it and a string with "CAT" in it, their types are identical. C# Span<T> deliberately can't live on the heap. The CLR doesn't want to cope with this type, and by ensuring it's part of your program's stack any questions about the lifetime of the Span are obviated and tricky-to-reason about garbage collection problems don't arise. Go's slices are very strange because Go's arrays are like those in Rust, their size is part of their type - and yet Go's slices can append. This is achieved by actually creating a new array and copying all the data for the slice into the new array whenever Go sees fit.
- tialaramex 4y agoBut remember all C++ defaults are wrong, and so of course std::span isn't bounds checked While your Rust slice will yell at you (at runtime if it can't figure it out at compile time) when you try to index into the fifteenth item in a ten item slice, C++ has Undefined Behaviour in this case.
- raverbashing 4y ago> But remember all C++ defaults are wrong Honest truth right here.
- germandiago 4y agoSome are not. Many are.
- BenFrantzDale 4y agoTrue. I love C++ but think “don’t pay for what you don’t use” should err on the side of safety over speed when it comes to what “pay” means. I’d rather `operator[]` be bounds-checked and occasionally have to call `v.data()[i]` or `v.unchecked_at(i)` when profiling justifies it.
- flohofwoe 4y agoIs a C++ std::span object like std::string_view in that it can outlive the data it points to? If yes, that's hardly an improvement over a raw C pointer/size pair.
- frozenport 4y agoIts an "input only" type, aka don't return it, but use it as an argument
- flohofwoe 4y agoThat's just by convention though, right? C++ doesn't prevent me from storing the std::span somewhere so that it outlives the scope of the called function? IMHO it's disappointing that C++ adds new memory management footguns without first fixing the basics (like at least some rudimentary lifetime tracking to help with such situations).
- bartwe 4y agoc# got this right, enforcing the lifetime of Span<>
- BenFrantzDale 4y agoI keep considering writing a `unique_span` and `shared_span`. Really `span` or (a type it’s based on) should have been templated on the pointer type, so a `span<shared_ptr<const T[]>>` for example.
- germandiago 4y agoYes, in C++ you can also do this: ``` int & a = *new int; ``` And it would be as stupid as juggling with spans around liberally.
- pjmlp 4y agoNope, unless you're compiling in debug mode, or force enable bounds checking in release.