@deezo
Do you need the std::span specifically? Some range adaptor would be legal and likely as performant with optimizations enabled.
i’m making an API function for a vectored write based on libuv, and libuv’s own APIs, including structs, are supposed to be hidden. The idea here is that:
- libuv has a struct type
uv_buf_t (that’s the sigma here), and libuv’s vectored write function accepts a pointer to an array of those. - user of my API instead constructs an array of my class let’s call it
IoVec (the ligma in the example), and passes a span of those to my function, which then turns it into a pointer to an uv_buf_t array to pass it to libuv, importantly without making any extra allocations (otherwise it would be less annoying to just have my func accept a span<span<char>> instead)
some fancy adaptor would likely overcomplicate things. maybe having user pass an array of uv_buf_ts directly could work, but ehhhh
i got curious and looked into how libuv itself does it, after all it’s getting a uv_buf_t array pointer and needs to pass the libc type struct iovec to writev, and those are, too, different types. and oh my god. it just casts the uv_buf_t* to struct iovec*!! the structs don’t even have the same members. iovec has a void *iov_base as the first member, uv_buf_t has char *base first member, it’s so blatantly wrong. The devs literally couldn’t care less about UB, just “oh its the same bits and bytes on the memory who cares”
Maybe if the library i am using is so careless about UB, i don’t really need to care about it too much in the program that uses the library either. after all the cat is kind of out of its bag already. Though thinking about it, both libuv’s UB and my UB would be very unlikely to ever cause any issues, as the actual invalid access is occuring across a translation unit boundary. just gotta be careful with LTO :-)