Main Content

AUTOSAR C++14 Rule A18-9-2

Forwarding values to other functions shall be done via: (1) std::move if the value is an rvalue reference, (2) std::forward if the value is forwarding reference

Since R2020b

Description

Rule Definition

Forwarding values to other functions shall be done via: (1) std::move if the value is an rvalue reference, (2) std::forward if the value is forwarding reference.

Rationale

You can pass an object efficiently to a function by casting the object to an rvalue and taking advantage of move semantics.

  • If you are forwarding an rvalue reference to a function, use std::move to cast the object to an rvalue.

  • If you are forwarding a forwarding reference (or universal reference) to a function, use std::forward to cast the object to an rvalue if and only if the object is bound to an rvalue. A forwarding reference might be bound to an rvalue or an lvalue. For the purposes of this rule, objects with type auto && are considered as forwarding references.

Using std::move with forwarding references might result in an unexpected modification of an lvalue. Using std::forward with rvalue references is possible but it is error-prone and might increase the complexity of your code.

Polyspace Implementation

  • Polyspace® flags the use of std::move to forward a forwarding reference to a function, including objects of type auto &&.

  • Polyspace flags the use of std::forward to forward an rvalue reference to a function.

  • Polyspace does not flag the use of std::move or std::forward if no forwarding to a function takes place. For instance, in this code snippet, no defect is raised on the use of std::move with forwarding reference b2 and the use of std::forward with revalue reference b1.

    template <typename T1, typename T2>
    void func(T1& b1, T2&& b2)
    {
        const T1& b10 = std::forward<B>(b1);
        const T2& b20 = std::forward<B>(b2);
        const T1& b11 = std::move(b1);
        const T2& b21 = std::move(b2);
    }

Troubleshooting

If you expect a rule violation but Polyspace does not report it, see Diagnose Why Coding Standard Violations Do Not Appear as Expected.

Examples

expand all

#include <cstdint>
#include <string>
#include <utility>


class A
{
public:
    explicit A(std::string&& s)
        : str(std::move(s)) // Compliant
    {
    }

private:
    std::string str;
};

template <typename ...T>
void f1(T...t);



template <typename T1, typename T2>
void func(T1&& t1, T2& t2)
{
    f1(std::move(t1));            // Non-compliant
    f1(std::forward<T1>(t1));     // Compliant

    f1(std::forward<T2>(t2));     // Non-compliant
    f1(std::move(t2));            // Compliant
}

void func_auto(A& var)
{
    auto&& var1 = var;
    f1(std::move(var1));                    // Non-compliant
    f1(std::forward<decltype(var1)>(var1)); //Compliant
}

void main()
{
    int32_t i;
    func(0, i);
}

In this example, template function func forwards parameters t1 and t2 to function f1. Polyspace flags the use of std::forward with t2 because this parameter is an rvalue reference (type T&).

Polyspace also flags the use of std::move with t1 because this parameter is a forwarding reference (type T&&). If t1 is initialized with an lvalue, the move might result in an unexpected modification of the parameter. Similarly, Polyspace flags the use of std::move in func_auto because objects of type auto&& are considered as forwarding references.

Check Information

Group: Language support library
Category: Required, Automated

Version History

Introduced in R2020b