Date: Tue, 20 Jun 2023 14:04:55 +0400
I've been working on improving trivial relocation proposals and I think
I've found a new tool in a language we don't use
About relocation:
There are few possibilities to create move ctor:
1. trivial memcpy
2. exchange with default state
3. self reference scenario
4. do not have move ctor at all
We already have = default, which is may be deducted as 'trivially movable',
but we dont have 2 scenario in standard
So i propose
struct Type {
Type(Type&&) = swap;
Type& operator=(Type&&) = swap;
};
Which will default construct Type and then adl swap all fields and
bases.(or swap with right operand for operator=)
So compiler will have ability to proove +- ALL not self reference
scenarios, then we can add trait
is_not_self_reference<T>
(traits checks if T has field or base class with non 'swap'/'default' move
recursivelly)
This solution that will improve the old code without changes, reduce the
number of boilerplate and make the code more expressive.
ABOUT LANGUAGE TOOL WE DONT USE
What if we add trait is_trivially_destructible_after_move?
You can ask - how?
It's simple, almost all types have a constexpr default constructor and
destructor, even std::any.
So let the compiler create a type value, then destroy it at compilation and
find out if this code had any side effects!
In this case, if 'if consteval' or 'is_constant_evaluated' is used, then
both branches are checked
(if you are asking why you think type is default constructed after move -
it is deductible with 'swap' or 'default' moves)
I've found a new tool in a language we don't use
About relocation:
There are few possibilities to create move ctor:
1. trivial memcpy
2. exchange with default state
3. self reference scenario
4. do not have move ctor at all
We already have = default, which is may be deducted as 'trivially movable',
but we dont have 2 scenario in standard
So i propose
struct Type {
Type(Type&&) = swap;
Type& operator=(Type&&) = swap;
};
Which will default construct Type and then adl swap all fields and
bases.(or swap with right operand for operator=)
So compiler will have ability to proove +- ALL not self reference
scenarios, then we can add trait
is_not_self_reference<T>
(traits checks if T has field or base class with non 'swap'/'default' move
recursivelly)
This solution that will improve the old code without changes, reduce the
number of boilerplate and make the code more expressive.
ABOUT LANGUAGE TOOL WE DONT USE
What if we add trait is_trivially_destructible_after_move?
You can ask - how?
It's simple, almost all types have a constexpr default constructor and
destructor, even std::any.
So let the compiler create a type value, then destroy it at compilation and
find out if this code had any side effects!
In this case, if 'if consteval' or 'is_constant_evaluated' is used, then
both branches are checked
(if you are asking why you think type is default constructed after move -
it is deductible with 'swap' or 'default' moves)
Received on 2023-06-20 10:05:08