matrix: fix slice to slice assignment to do deep copy #22574
Merged
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Solved Problem
@bresch warned me about this bug report yesterday: #22565
We started debugging and were puzzled why the assignment of
a.xy() = b.xy()
with twoVector3f
s did not callSlice::operator=()
which implements a deep copy of the submatrix in b, in this case the first two elements.@jwidauer kindly spent some time analyzing the case. He found out by separating the steps and explicitly deleting constructors and the detailed output of clang that the autogenerated implicit default copy constructor of
Slice<Type, P, Q, M, N>
is the preferred template match overSlice<Type, P, Q, M, N> &operator=(const Slice<Type, P, Q, MM, NN>)
when the original unsliced size of matrixb
(MM
andNN
) exactly matches the size of matrixa
(M
andN
). As a result the pointer ina.x()
was replaced with a thin copy ofb.xy()
and none of the elements were copied to the original matrixa
.Fixes #22565
Solution
Explicitly define
Slice<Type, P, Q, M, N> &operator=(const Slice<Type, P, Q, M, N>)
with exactly matching original sizesM
andN
and make it call the original deep copy implementation. The compiler then gives a warning if we don't also explicitly declare the default copy constructor without the assignment operator to do what it originally did.Changelog Entry
Test coverage
The added test now does what it should.
Position lock in Position mode
Before:
After:
Fake position fusion:
I have no idea how to verify this. @bresch could you have a quick look at the change indicator?
Context
In
https://github.com/PX4/PX4-Autopilot/pull/20440/files#diff-6a93912921c62df6bced857c3dea68c3c275d25faa3f6c78866eafedc4e5612fR113
and
https://github.com/PX4/PX4-Autopilot/pull/20021/files#diff-61244855f5e70ce3cf45228c9915530a01583ea7906fb25b93547c8ff839ad74R513
we started using assignments of a slice to a slice
a.xy() = b.xy()
with twoVector3f
s. We expected this to assign the elements of sliceb
to the elements of slicea
just like how it works when doinga.xy() = Vector2f()
. Turns out the later case is unit tested, the first one not.