Date: Wed, 29 Oct 2025 11:28:06 -0400
On Wed, Oct 29, 2025 at 11:11 AM Frederick Virchanza Gotham via
Std-Proposals <std-proposals_at_[hidden]> wrote:
>
> I'm saying that there are four different classifications when it comes to
> a type's relocatability:
>
> (Type 1) Cannot be relocated
> (Type 2) Can be relocated by a simple memcpy
> (Type 3) Can be relocated by an algorithm built into the compiler
> (Type 4) Can be relocated by a custom-implemented relocator algorithm
> provided by the author of the class
>
> So, on arm64e when you relocate a simple polymorphic object, you get Type
> 3. (Whereas on every other compiler it's only Type 2).
>
> Type 4 would be the likes of std::string in short-string optimisation mode.
>
libstdc++'s std::string is Type 4.
libc++'s and MSVC's std::string are Type 2.
See
https://quuxplusone.github.io/blog/2019/02/20/p1144-what-types-are-relocatable/
.
Notice that in Type 4, the "custom-implemented algorithm" can actually be a
generic algorithm: to relocate an object, all you have to do is
move-construct it and destroy it. These are of course type-specific
operations — T::T(T&&) and T::~T() for some specific T.
The benefit of Type 2 is that you can do it without any knowledge of what T
is. This means you can use Type 2 types with type-erased, C-style
"algorithms" such as:
- realloc (which "relocates" all the elements in the reallocated buffer by
relocating their bytes)
- qsort (which shuffles elements by relocating their bytes)
- the internals of std::function and std::move_only_function (which, in
order to be efficiently movable, want to "relocate" the contained object
without knowing its type — this means they want to contain only objects
that are Type 2)
Your Type 3 is very fuzzy. Consider that *any* algorithm can be "built into
the compiler"; there's nothing particularly special about polymorphic
objects here. For example: libstdc++ and libc++ both have non-Type-2
std::list. Relocating their std::list requires updating pointer fields in
the head and tail nodes. This operation is easily codegennable by the
compiler — in fact std::list is constexpr in C++26; none of its methods are
*allowed* to be opaque to the compiler — and this operation cannot possibly
fail at runtime. Therefore, arguably, lib{std,}c++'s std::list (with the
default allocator) ought to be considered Type 3, not Type 4.
There's a very clear physical delineation between Type 1, Type 2, and "all
the rest." The line between Type 3 and Type 4 is not physical but
linguistic, and arbitrary.
–Arthur
Std-Proposals <std-proposals_at_[hidden]> wrote:
>
> I'm saying that there are four different classifications when it comes to
> a type's relocatability:
>
> (Type 1) Cannot be relocated
> (Type 2) Can be relocated by a simple memcpy
> (Type 3) Can be relocated by an algorithm built into the compiler
> (Type 4) Can be relocated by a custom-implemented relocator algorithm
> provided by the author of the class
>
> So, on arm64e when you relocate a simple polymorphic object, you get Type
> 3. (Whereas on every other compiler it's only Type 2).
>
> Type 4 would be the likes of std::string in short-string optimisation mode.
>
libstdc++'s std::string is Type 4.
libc++'s and MSVC's std::string are Type 2.
See
https://quuxplusone.github.io/blog/2019/02/20/p1144-what-types-are-relocatable/
.
Notice that in Type 4, the "custom-implemented algorithm" can actually be a
generic algorithm: to relocate an object, all you have to do is
move-construct it and destroy it. These are of course type-specific
operations — T::T(T&&) and T::~T() for some specific T.
The benefit of Type 2 is that you can do it without any knowledge of what T
is. This means you can use Type 2 types with type-erased, C-style
"algorithms" such as:
- realloc (which "relocates" all the elements in the reallocated buffer by
relocating their bytes)
- qsort (which shuffles elements by relocating their bytes)
- the internals of std::function and std::move_only_function (which, in
order to be efficiently movable, want to "relocate" the contained object
without knowing its type — this means they want to contain only objects
that are Type 2)
Your Type 3 is very fuzzy. Consider that *any* algorithm can be "built into
the compiler"; there's nothing particularly special about polymorphic
objects here. For example: libstdc++ and libc++ both have non-Type-2
std::list. Relocating their std::list requires updating pointer fields in
the head and tail nodes. This operation is easily codegennable by the
compiler — in fact std::list is constexpr in C++26; none of its methods are
*allowed* to be opaque to the compiler — and this operation cannot possibly
fail at runtime. Therefore, arguably, lib{std,}c++'s std::list (with the
default allocator) ought to be considered Type 3, not Type 4.
There's a very clear physical delineation between Type 1, Type 2, and "all
the rest." The line between Type 3 and Type 4 is not physical but
linguistic, and arbitrary.
–Arthur
Received on 2025-10-29 15:28:22
