Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Modify rule S5500: mention std::ranges::move and rewrite RSPEC (CPP-5219) #3933

Merged
merged 15 commits into from
May 23, 2024
Merged
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 26 additions & 9 deletions rules/S5500/cfamily/rule.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,11 @@ This might lead to bugs.

This issue can be resolved in multiple ways:

// We do not mention std::move_backward or std::ranges::move_backward to keep things simple.
// Those functions are assumed to be less frequently needed.

* Generally, `std::move` can be used to move such arguments;
* For containers, {cpp}23 `std::views::as_rvalue` can be used to move their elements;
* For containers, {cpp}23 `std::views::as_rvalue` or {cpp}20 `std::ranges::move` can be used to move their elements;
* It is also possible to use a range-based for loop to move elements.

This rule does not apply when the argument is a forwarding reference.
Expand All @@ -28,13 +31,18 @@ public:
class DrawingStore {
std::vector<Shape> store;
public:
void insertShape(Shape&& shape) {
void insertVisibleShape(Shape&& shape) {
if (shape.isVisible()) {
store.emplace_back(shape); // Noncompliant, call to std::move is expected
}
}

void insertAllShapes(std::vector<Shape>&& shapes) {
void insertAllShapes(std::vecto<Shape>&& shapes) {
// Noncompliant: the elements of shapes are not moved.
std::ranges::copy(shapes, std::back_inserter(store));
}

void insertAllVisibleShapes(std::vector<Shape>&& shapes) {
for (auto& s : shapes) {
if (s.isVisible()) {
store.emplace_back(s); // Noncompliant, call to std::move is expected
Expand All @@ -58,13 +66,18 @@ public:
class DrawingStore {
std::vector<Shape> store;
public:
void insertShape(Shape&& shape) {
void insertVisibleShape(Shape&& shape) {
if (shape.isVisible()) {
store.emplace_back(std::move(shape)); // Compliant
}
}

void insertAllShapes(std::vector<Shape>&& shapes) {
void insertAllShapes(std::vecto<Shape>&& shapes) {
// Compliant: use "move" instead of "copy".
std::ranges::move(shapes, std::back_inserter(store));
}

void insertAllVisibleShapes(std::vector<Shape>&& shapes) {
for (auto& s : shapes) {
if (s.isVisible()) {
store.emplace_back(std::move(s)); // Compliant
Expand All @@ -74,11 +87,11 @@ public:
};
----

Alternatively, `insertAllShapes` could also be rewritten like this using {cpp}23:
Alternatively, `insertAllVisibleShapes` could also be rewritten like this using {cpp}23:
marco-antognini-sonarsource marked this conversation as resolved.
Show resolved Hide resolved

[source,cpp]
----
void insertAllShapes(std::vector<Shape>&& shapes) {
void insertAllVisibleShapes(std::vector<Shape>&& shapes) {
std::ranges::copy_if(
shapes | std::views::as_rvalue,
std::back_inserter(store),
Expand Down Expand Up @@ -123,7 +136,7 @@ Shape&& updateShape(Shape&& shape) {
}
----

Due to all of the above, this rule does not treat `return p` as an exception in {cpp} standard prior to {cpp}23,
Due to all of the above, this rule does not treat `return p` as an exception in {cpp} standard before {cpp}23,
and requires the explicit move `return std::move(p)`.

In contrast to returning local (stack) variables, named return value optimization (NRVO)
Expand All @@ -134,13 +147,17 @@ does not apply to function parameters, so an explicit `std::move` call has no im

=== Documentation

// Not linking to the _backward versions, to the std::move(start, end, result) overload,
// or std::make_move_iterator function to keep the number of links manageable.

* {cpp} reference - https://en.cppreference.com/w/cpp/utility/move[`std::move`]
* {cpp} reference - https://en.cppreference.com/w/cpp/algorithm/ranges/move[`std::ranges::move`]
* {cpp} reference - https://en.cppreference.com/w/cpp/ranges/as_rvalue_view[`std::ranges::views::as_rvalue`]
* {cpp} reference - https://en.cppreference.com/w/cpp/language/copy_elision[Copy elision]

=== External coding guidelines

* {cpp} Core Guidelines - https://github.com/isocpp/CppCoreGuidelines/blob/e49158a/CppCoreGuidelines.md#f18-for-will-move-from-parameters-pass-by-x-and-stdmove-the-parameter[F.18: For "will-move-from" parameters, pass by `X&&` and `std::move` the parameter]
* {cpp} reference - https://en.cppreference.com/w/cpp/language/copy_elision[Copy elision]

=== Related rules

Expand Down
Loading