1. 16
  1.  

  2. 3

    Strongly typed typedefs is one of those things that C++ has forced every big project to reinvent over and over (that, slice, synchronized and serialization). Commonly (at least before C++17) using tag types.

    1. 2

      I “invented” a slice type in 2014 and it’s been a mainstay of my C++ coding ever since. So damn useful. I know we have string_view now, but I don’t feel right using that for stuff other than actual strings.

    2. 3

      I just realized that your username is spelled backwards, I recognize it as a c++ regular, but thought it was something Nordic… Funny, and a great blogpost. I’ve written a few c++17 classes, mostly constexpr capable for volumetric calculations (millilitres, floz), since that is what we use for our application, before that it was all uint8, with descriptive names (not) like amount.. you had to guess if it was millilitres, decilitres, pulses, seconds or whatever… Strong types are so wonderful

      1. 1

        Thanks! Constexpr is another thing I want to blog about — I made some constexpr value types like that in another project, and had the brainstorm that I could write tests for them inside static_assert statements, and have compile-time unit tests. It’s very fun to type a change in a method and see the test immediately flagged as a compile error in my IDE!

      2. 2

        I am curious about this definition:

        enum class byte : unsigned char {} ;
        

        Does it give you an ability to “access raw memory occupied by other objects” by virtue of inheriting from char, or is some compiler special casing required? If I make my own byte which inherits from char, will this opt me out of TBAA?

        1. 2

          No, std::byte gets special dispensation, like [unsigned] char, to free itself from strict aliasing in the standard. If you do it yourself, it won’t work: https://gcc.godbolt.org/z/Whs1Y9drE

          1. 2

            This is not a real inheritance, this is a specification of the underlying type (which can only be a fundamental integral type). The main use is to prevent the change of the underlying representation when changing the enumerator set/values. And, yes, you still need an explicit cast.

            EDIT: See http://eel.is/c++draft/dcl.enum, specifically verses 5-10.

          2. 2

            A similar feature exists in rust, where they call them “newtypes”. It’s really nice to have.

            1. 2

              Yes, though there’s no one-liner for it in Rust. I thought there was, but when I looked it up yesterday I only found the struct-based version. (Which, as in C++, is more powerful than an enum, it just takes some more work.)

              Swift also uses struct wrapping — IIRC, even the basic integer types are defined as structs.

              1. 2

                No one-liner? Are you looking for pub struct Bar(Foo);, or am I mis-understanding what you mean?