[Development] What's Q_PRIMITIVE_TYPE for?

Ville Voutilainen ville.voutilainen at gmail.com
Fri Nov 13 09:47:56 CET 2020

On Thu, 12 Nov 2020 at 17:11, Lars Knoll <lars.knoll at qt.io> wrote:

> Language Lawyer Hat: is_trivial is the wrong type trait when it comes to detect trivial copiability anyhow, example:
>  struct S { int i; S operator=(const S &)=delete; };
> is trivial and not copy assignable. Isn't C++ a fun language to work with... :P
> Sigh… is_trival implies is_trivially_copyable. That one implies https://en.cppreference.com/w/cpp/named_req/TriviallyCopyable, which implies that all “eligible” copy/move constructor and assignment operators are trivial. But they don’t disallow deleting them (as that makes the operator not eligible).
> So what are the correct traits then? Sounds like “is_trivially_copyable and no deleted copy/move operators” is about what we need :/

Well, even libstdc++ uses is_trivial for some memcpy optimizations,
but that chooses strictly fewer types than is_trivially_copyable
would. However, the optimizations I'm talking about are in
std::{uninitialized_,}copy - and there's checks for more than just
is_trivial, because
the really fun part of is_trivial and is_trivially_copyable is that
they tell you whether some sort of memcpy is valid, but that might
not be the kind of memcpy you're doing. Meaning that, when you want to
memcpy over raw storage, you should check
is_trivially_copy_constructible, and if you're memcpying over existing
objects, you should check is_trivially_copy_assignable.
Those traits will check whether the relevant operation is well-formed,
including "not deleted".

Using is_trivially_copy_constructible and is_trivially_copy_assignable
thus also avoids the problem Thiago mentioned, i.e.
UB when skipping a non-trivial or deleted operation. However, in our
code, it's not so simple, because in some cases
we *do* bit-blast non-trivial types, because the standard doesn't
provide relocatability.

More information about the Development mailing list