Hacker News new | past | comments | ask | show | jobs | submit login
Trivial, but not trivially default constructible (quuxplusone.github.io)
10 points by hk__2 on April 8, 2024 | hide | past | favorite | 5 comments



Never realized concepts implied you can have multiple default constructors, that's hilarious. This is still a useful feature though. People complain a lot about C++ corner cases, but this is one you would probably never hit in real code, and `requires` clauses does a lot to clarify type requirements and provide better error messages (instead of getting a ten page template stack trace ending in some extremely cryptic type requirement for some nested class, you just get a short error message at the require site, explaining why a certain type isn't valid).


> The rule is: A type T is trivially fooable if and only if its foo operation is (known to the compiler to be) equivalent to the same foo operation on T’s object representation (i.e., an array of unsigned char).

Probably not if there's any padding in the structure. Decently unlikely that T has a defined object representation at all though maybe that's changed in newer standards.


Author here. :) I'm not saying that T's object representation needs to be known to the programmer, or portable, or unique, or anything concrete like that. This is about a relationship between the foo operation on T itself and the foo operation on T's object representation.

For example, we say that T is trivially copy-constructible iff T's copy constructor is defined such that making a copy of a T object is tantamount to making a copy of T's object representation (i.e., a memcpy). Given these two functions...

  struct ObjRep { alignas(T) char data_[sizeof(T)]; };
  void copy_value(T *s, T *d) { ::new (d) T(*s); }
  void copy_repr(ObjRep *s, ObjRep *d) { ::new (d) ObjRep(*s); }
...if T is trivially copy-constructible, then these functions can (and in practice will) generate exactly the same code.

Certain types are guaranteed by the Standard to be trivially fooable for certain foos (e.g. `int` is guaranteed to be trivially copyable, and so is `std::string_view` since C++23). Vice versa, it's often physically obvious when a type can't be trivially fooable; e.g. `std::string_view` can't possibly be trivially equality comparable. For most types, the Standard makes no guarantee, so different vendors may do different things... but each individual vendor must do some thing! And for most of these foos, we can just query a type-trait to find out what the compiler has done in the case of any given T.

Here's a godbolt where you can just fill in some data members and user-provided special member functions for `T`, and see the codegen for yourself. https://godbolt.org/z/97d3o3vbW

You mentioned padding bytes. Padding prevents trivial comparability, but does not affect any other trivial fooability that I can think of off the top of my head.


I didn’t know what this was. Just thought “that’s such a C++ title”.


I love how trivial things become complicated in C++, to the point that the very definition of trivial is hard to grok!




Consider applying for YC's Fall 2025 batch! Applications are open till Aug 4

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: