Forward arguments in ResourceLimitedVector::emplace_back - #6527
Open
MaxFreedomPollard wants to merge 1 commit into
Open
Forward arguments in ResourceLimitedVector::emplace_back#6527MaxFreedomPollard wants to merge 1 commit into
MaxFreedomPollard wants to merge 1 commit into
Conversation
emplace_back takes a forwarding reference pack (Args&& ... args) and
documents it as "Arguments forwarded to construct the new element", but
expands the pack as plain lvalues:
collection_.emplace_back(args ...);
Every argument therefore reaches the underlying collection as an lvalue.
An rvalue argument is copied instead of moved, and a move-only element
type does not compile at all, because the pack is instantiated as
std::vector<std::unique_ptr<int>>::emplace_back<std::unique_ptr<int>&>.
The sibling push_back(value_type&&) does move correctly, so the two
entry points disagree on identical input.
Expand the pack with std::forward<Args>(args)... and include <utility>
for it. Add two regression tests: one counting copies and moves for an
lvalue and an rvalue argument, one emplacing a std::unique_ptr<int>.
Signed-off-by: Max Freedom Pollard <272618364+MaxFreedomPollard@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Description
ResourceLimitedVector::emplace_backtakes a forwarding reference pack and its Doxygen block documents it as "Arguments forwarded to construct the new element", butinclude/fastdds/utils/collections/ResourceLimitedVector.hpp:227expands that pack as plain lvalues:collection_.emplace_back(args ...);. The value category of every argument is dropped, so an rvalue argument is copied instead of moved, and a move-only element type does not compile at all because the underlying call is instantiated asemplace_back<std::unique_ptr<int> &>. The siblingpush_back(value_type&&)a few lines above doescollection_.push_back(std::move(val)), so the two entry points behave differently on identical input.The fix is to expand the pack as
collection_.emplace_back(std::forward<Args>(args)...)and add#include <utility>for it. The signature, the Doxygen block and the mangled names are unchanged, so this only makes the code do what the documentation already said.No call site inside the repository changes behaviour. The only
emplace_back(std::move(...))calls undersrc/are onstd::vectormembers (NetworkFactory::mRegisteredTransportsand theconsumersvector inSharedMemLog.hpp), not on aResourceLimitedVector.Two regression tests are added to
test/unittest/utils/ResourceLimitedVectorTests.cpp:emplace_back_forwards_argumentscounts constructions and asserts an lvalue is copied once and an rvalue is moved once, andemplace_back_move_only_valueemplaces astd::unique_ptr<int>and checks the source is left empty.Verification
Apple clang 17 on macOS, building
ResourceLimitedVectorTests.cppstandalone against the unmodified header and against the patched one.Against the unmodified header from 0f5c9b9 the file does not compile, and the diagnostic points straight at line 227:
Removing only
emplace_back_move_only_valueso the rest builds against the unmodified header, the other new test fails and the five pre-existing tests pass:Against the patched header all seven tests pass, with
-Wall -Wextraand no warnings:A small probe counting copy and move constructions shows the difference directly. Unmodified header:
emplace_back(std::move(t)) -> copies=1 moves=0andpush_back(std::move(t)) -> copies=0 moves=1. Patched header:emplace_back(std::move(t)) -> copies=0 moves=1andpush_back(std::move(t)) -> copies=0 moves=1.Both changed files are left byte for byte unchanged by uncrustify 0.78.1 with the project configuration.
Backports
@Mergifyio backport 3.2.x
The same expansion is present on 3.6.x, 3.2.x, 2.14.x and 2.6.x. On 2.14.x and 2.6.x the header lives at
include/fastrtps/utils/collections/ResourceLimitedVector.hpp, so those branches need a manual port rather than a clean cherry-pick. Happy to open them if you want the fix there.Contributor Checklist
versions.mdfile (if applicable).Reviewer Checklist