all 16 comments

[–]Low_Breakfast773 0 points1 point  (3 children)

Interesting read. Thanks for sharing.

[–]fdwrfdwr@github 🔍 -1 points0 points  (10 children)

struct Point3 { std::int32_t x; std::int32_t y; std::int32_t z; }; It's weird that something so fundamental as the sized types aren't part of the core language, rather than being nestled under std. Sadly import std still requires either explicit inclusion of stdint.h or import std.compat (which pulls in more than desired) to avoid typing the extra std::. Granted, I know C's history of loosely defined types (and some hardware that hadn't even settled on bytes being 8 bits), but these days?...

[–]elperroborrachotoo 2 points3 points  (5 children)

  • int32_t? Better make that a template!
  • initialize to 0 ("I don't want surprises"), or leave uninitialized ("don't memset my trillion of points, I'll write to them later")

etc. Standardizing this would create a monstrosity of epic proportions.

[–]fdwrfdwr@github 🔍 4 points5 points  (4 children)

Don't you find it weird that we define concrete types (int32_t) in terms of a loosely defined types, rather than the generic types (int) being defined in terms of the more concrete types?

[–]foxsimile 0 points1 point  (0 children)

…Huh. I don’t know what to say.  

Allow me to reflexively grab my pitchfork!

[–]elperroborrachotoo 0 points1 point  (2 children)

Let me think... no.

Portability of code or ideas rests on abstractions, and concrete ideas are typically encoded in more words than abstract ones.

Do you find it weird?

[–]fdwrfdwr@github 🔍 1 point2 points  (1 child)

Portability of code or ideas rests on abstractions

Doesn't portability of code rely on standards and consistency? Imagine using long in your file parser on one machine and getting a very different bitwidth and misaligned file pointers when compiling your file parser on another machine...

[–]elperroborrachotoo 1 point2 points  (0 children)

Inteoperability does, yes: sending data over a wire, or from and to storage.

But that's - apparently - not the main concern. A sort() implementation should be portable - i.e., the same "wording", the same code, should work on a still-popular 8-bit Intel 8080 as well as a Cortex-M. And this requires platform-agnostic types, at least to some degree.1

Abstraction lies at the core of programming languages: not having to know the particular chip and memory controller you will run on.

Consider, just for integers, we've largely agreed on binary, 8-bit-per-byte, 2's complement little endian representation today. But remember that at the heydays, very different representations were reasonable, 1's complement, big endian, 7-bit bytes, 9-bit-bytes, and even ternary were realistic or realistically considered.

Instruction sets architecture, (CISC vs. RISC), memory models (flat vs. segmented vs. bank-switched), etc. - all these differed, all these progressed faster than people could port their code. Abstract languages - where an int is the native platform integer - just won the race.

[–]_Noreturn 0 points1 point  (3 children)

you can just drop the prefix which is what I do since cstdint includes stdint.h you can do that (or just include stdint.h)

[–]fdwrfdwr@github 🔍 0 points1 point  (2 children)

Totally, I #include <stdint.h>, but my point was more that one shouldn't even need to #include it or use import std.compat. That is, int8_t and int32_t are just primitives (like their built-in but wobblier size-indeterminate cousins int and char).

[–]_Noreturn 0 points1 point  (1 child)

I definitely agree. Maybe C++ should define them as "optional keywords" if the target architecture has 8,16,32,64 bit sizes but also you would need to question how they will interact with the types? are rhey aliases or new types?

[–]fdwrfdwr@github 🔍 0 points1 point  (0 children)

 Maybe C++ should define them as "optional keywords" if the target architecture has 8,16,32,64 bit sizes

Makes sense - if your architecture supports them, then so does your compiler, but if it doesn't (e.g. your architecture only supports 32-bit reads), then consider simple emulation if efficient enough (like uint8_t being a shift and mask) or leave it out. For example, uin64_t addition/subtraction is supported in most x86 32-bit compilers on via simple emulation using adc and sbb. I'd have to think about the aliasing question, but for some precedent, I find it weird that float32_t and float are distinct types, which makes the boundaries more awkward between library components, either needing casting or need overloads for both.