Hacker News new | ask | show | jobs
by thomasmg 4 days ago
I don't have a strong opinion what is better in this case, but my view is:

> document and express intent clearly

Arguably, the void* does that as well?

> Any seasoned C++ developer seeing this knows what this reinterpret_cast means.

Same for void*?

> it's a bit more text to read

If you have to call it many times, this adds up.

> Some might also say it complexifies and uglifies the code

I think the point is that it adds security, which the other options don't. And, it doesn't add complexity on the caller, but only at one place: the implementation.

> makes it non-portable on top of that.

This can be solved.

2 comments

> Arguably, the void* does that as well?

Sort of (I mean: seeing void* and a size probably means 'arbitrary sequence of bytes' or something like that, but well it's void* so it can be like anything whereas with std::span you get more of a hint what's going on just based on the type), but not at the callsite which is what the author is referring to when it's about reinterpret_cast.

> I think the point is that it adds security, which the other options don't

Imo span also does that to some extent, but already when writing the code and not afterwards in e.g. static analysis. E.g. if I get an std:span<const char> I'd have to do counterintuitive things to misuse it. Annotating a void* still leaves it a void* which I then need to cast to char* if I think that's what it is intended.

Don't get me wrong: I've written my fair share of void* but these days I really feel like there's almost always a better thing which can be used instead. Though I do admit that since I've written and consumed a lot of code with such alternatives I'm not hindered by readability/apparent complexity of it anymore but I understand that's not the same for everyone.

> whereas with std::span you get more of a hint what's going on just based on the type

You don’t if it’s a span of bytes (or equivalent).

Encoding the length in a span is a meaningful thing. But the fact that it holds a random memory pointer labeled “byte” instead of “void” doesn’t change anything.

> Arguably, the void* does that as well?

How do you figure? The type is a pointer to quite literally anything, including nothing (ie a pointer that cannot be dereferenced). If you're working with bytes, indicate this with the type.

> The type is a pointer to quite literally anything

No, it can only be a pointer to an object. It can't be a pointer to a function, for example.

All pointers in C/C++ can point to “nothing”. Swapping “void *” for “byte *” is basically an aesthetic choice.
Right. So why not use a typed reference?
1. void * is a type

2. The functions in question here operate on raw memory. void * conveys the same information as byte *. It’s not untyped vs typed. It’s two different types that convey the same information but require slightly different mechanics to obtain.

3. The author explained his reasoning for preferring void * over byte * (or uint8_t *)

4. A reference also isn’t the same thing as a pointer in C++