Live data from Hacker News

The beauty and simplicity of the good old C-style void* in C++

giodicanio.com

121–130 of 182 posts

Re: The beauty and simplicity of the good old C-style void* in C++

#121

Earlier quoted context omitted.

Can you point to it? That doesn't sound like "the language forced all this extra baggage on it due to 'safety'" so much as the developers kept adding functions to the function without rethinking if and how they should.

My point was not about the safety of the code, it was about the expressiveness, which is also what the comment I replied to was about. If the parameter has an explicit type (instead of no type, as is normal in Ruby, or `void*`, which is the C equivalent), it forces the developer to consider the design of the function, instead taking the path of least resistance because they're inexperienced/incompetent/a large langua…

Forcing developers to consider and more is harmful though. You're arguing to put all of the forethought upfront, when you have the least context and least understanding of what can go wrong, and carrying that complexity forward rather than starting simple and refactoring over time.

Re: The beauty and simplicity of the good old C-style void* in C++

#122
post #119
post #106

Earlier quoted context omitted.

I think the article names hashing as a use-case, which I can somewhat still agree. Operations that only depend on the bytes, I guess. But yeah, most things worth saying about this article have been said here already

Hashing everything based on the byte representation breaks when you have a type where equality does not imply byte equality. Such as… floats (+0 and -0 are equal, but have different byte representation).

Depends on the use-case, hashing can also be used for checking integrity/change in which case you exactly want the behavior that only bit-exact-equality is desired, even for arbitrary structs. Maybe that's somewhat niche, I mention it as I have such a use-case actually.

Re: The beauty and simplicity of the good old C-style void* in C++

#123
post #106

Earlier quoted context omitted.

I think the article names hashing as a use-case, which I can somewhat still agree. Operations that only depend on the bytes, I guess. But yeah, most things worth saying about this article have been said here already

Sure, if the function is expected to not treat the data as anything but bytes, then it might be acceptable in narrow circumstances. But in such a case I'd argue FOR the ceremony, as a way of declaring from the API "The input is a sequence of bytes that I won't treat as anything other than a sequence of bytes", and declaring from each and every call site: "This is not a mistake; we really are 'converting' this struct…

I agree, the original article is rather questionable. I do not write code like the article advocates for. I would probably go for overloads for each data type I have considered and tested, or maybe something fully templated, or std::span/boost::span (hash function is, interesting enough, the very example boost docs give to illustrate boost::span).

Re: The beauty and simplicity of the good old C-style void* in C++

#124
post #25

Earlier quoted context omitted.

They did in C, from one of the language authors even, and it was not accepted. https://www.nokia.com/bell-labs/about/dennis-m-ritchie/varar... By the way, both Extended Pascal, Mesa/Cedar and Modula-2 have them, under the name of open arrays. Basically it took Go, C# and others for C++ to finally get its span. C probably never will.

Everybody knows that C++ did not invent the concept of spans and that it was late to the party. It doesn’t change the fact that (presumably) nobody made a proposal to the C++ standard.

> It doesn’t change the fact that (presumably) nobody made a proposal to the C++ standard.

There were proposals about this for many years. C++ is just a terrible programming language, standardized by a committee (WG21) which exists in large part to boost the ego of one man, Bjarne Stroustrup.

N3851 for example wants to name this idea "array_view" which like "string_view" is an impressively unwieldy name for a core language feature, because of course neither of these were actually proposed as core language features even though that's what they naturally should be -- but it is basically the slice type or as you (and modern C++) call it a "span".

It's true that you can't change facts but what you've got here was a belief which was unfounded, not a fact.

Re: The beauty and simplicity of the good old C-style void* in C++

#125
post #75

Earlier quoted context omitted.

Contrary to the FOSS compile from source culture, other platforms have a different point of view on ABI breaks. Which is why Valve ended up using Proton.

I'm pretty sure GCC has been ABI stable far longer that MSVC which used to break ABI every release. GCC was forced to break the std::string ABI by the C++11 standard and they have been lobbing ever since against ABI breaks.

GCC/libstdc++ just changed the ABI for std::variant: https://gcc.gnu.org/gcc-16/changes.html#libstdcxx

Re: The beauty and simplicity of the good old C-style void* in C++

#126
post #74

Earlier quoted context omitted.

> already existed in other languages This argument is moot. The issue with spans is not that they require cutting edge technology to deliver. Before commenting, perhaps you should research why even Denis Ritchie himself could not sell his idea to C. It's funny how every single idea that's rejected is blindly lauded as brilliant but silenced due to some kind of conspiracy, and only the ideas that emerged are somehow b…

Easy, even one of the author's could not change WG14 mind towards security. Governments,related cybersecurity agencies, and companies are the ones getting outraged when looking at money spent in cyber attacks due to memory corruption issues.

WG14 adopted variably modified types, a kind of dependent type. From a security standpoint it offers all the same qualities. It also in principle was easier to integrate from a backwards compatibility standpoint, with the exception of struct member analogs (which we now have but aren't yet standardized).

Maybe we would have been better off with Ritchie's counter proposal. But neither proposal was chiefly concerned with security, thus no proposals for, e.g., automatic bounds checking.

Re: The beauty and simplicity of the good old C-style void* in C++

#127

The real question here is: WHY are you passing a blob of memory rather than a struct that uses the type system to describe and enforce what the contents are? I don't mean dressing up an anonymous pointer, which the author rightly complains about. I mean WHY are you making an API that takes such a pointer to an unknown type to begin with? Whenever you change the structure within that blob, your type checker won't flag…

For type erasure (it’s sometimes useful), custom allocators, I/O, for example.

Then pass an uint8_t with size aka a span.

Re: The beauty and simplicity of the good old C-style void* in C++

#128

Earlier quoted context omitted.

Everybody knows that C++ did not invent the concept of spans and that it was late to the party. It doesn’t change the fact that (presumably) nobody made a proposal to the C++ standard.

> It doesn’t change the fact that (presumably) nobody made a proposal to the C++ standard. There were proposals about this for many years. C++ is just a terrible programming language, standardized by a committee (WG21) which exists in large part to boost the ego of one man, Bjarne Stroustrup. N3851 for example wants to name this idea "array_view" which like "string_view" is an impressively unwieldy name for a core la…

> There were proposals about this for many years.

I wrote "presumably", but you are 100% correct. I'm always happy to be proven wrong.

N3851 actually deals with multi-dimensional spans and goes way beyond a simple slice/span type. To me it seems closer to std::mdspan than std::span.

The earliest proposal I could find that does propose something similar to std::span dates back to 2012: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n33...

I really don't understand why this was not pursued further. At the very least, this should have made it into C++17 together with std::string_view.

> because of course neither of these were actually proposed as core language features even though that's what they naturally should be

Should it really? What would this even look like in C++? IMO std::span works perfectly fine as a library type.

> C++ is just a terrible programming language, standardized by a committee (WG21) which exists in large part to boost the ego of one man, Bjarne Stroustrup.

That's certainly not the reason why it was standardized. Pre-C++98 was wild west with every compiler offering there own (incompatible) idea of what C++ is. Yes, there are many problems with design by committee in general (and the C++ committee in particular), but there was a very good reason for standardizing the language. The committee is not a one man show and there are many occasions where Bjarne has publicly voiced his frustration and disagreement.

Re: The beauty and simplicity of the good old C-style void* in C++

#129
post #77

Earlier quoted context omitted.

Everybody knows that C++ did not invent the concept of spans and that it was late to the party. It doesn’t change the fact that (presumably) nobody made a proposal to the C++ standard.

Microsoft made the proposal for C++, after Midori project, and Office security improvements. Which by your comment, you have no clue about how it came to be. Proposal is linked in another comment of mine.

Well, you could have linked an actual proposal instead of dropping some cool facts about C, Extended Pascal, Mesa/Cedar and Modula-2, as if that explained anything.

Re: The beauty and simplicity of the good old C-style void* in C++

#130

Earlier quoted context omitted.

In general, you're right. The exception that I could think of is a "dump memory" function. You take a pointer to something (who cares what it is), and print out the bytes there. That I could see taking a void*. But that's a really limited case. In general, yes, you do not want to be dealing with blobs of memory as arguments. You want to be dealing with things that are known to be the right kind of thing as arguments.

But parent is right, you have to cast it anyways before reading from it, so might as well take the right type from the beginning.

Anything can be aliased by char, unsigned char, std::byte (as well as signed char in C), and usually uint8_t == unsigned char, thus by extension any valid void pointer can be cast to u8*.

Thus void*+size is usually the right type if ones only care for the memory representation of an object (cstring functions like memcpy, etc.)

Most likely one would have both overloads:

    void Hexdump(const void *p, size_t size); // (1)
    
    template  // (2)
    inline void Hexdump(const T &obj) {
         return Hexdump(&obj, sizeof(T));
    }
With (2) being a wrapper to (1) that compilers will almost always inline, avoiding monomorphization costs (and (2) can also accept rvalues as argument).

(1) could also take std::span, but (void*, size) is the more common idiom, more convenient to use and to read , as it is unambiguous which overload it is.

Post reply on HN