メインコンテンツ

AUTOSAR C++14 Rule A18-9-4

An argument to std::forward shall not be subsequently used

説明

ルール定義

An argument to std::forward shall not be subsequently used.

根拠

一般に、転送参照パラメーターを別の関数に渡すために関数テンプレートで std::forward を使用します。パラメーターの value カテゴリによっては、移動操作によってパラメーターのリソースが別のオブジェクトに転送される場合があります。

rvalue パラメーターの場合、std::forward の呼び出し後に移動されると状態が不確定になるため、このパラメーターを再利用しないでください。

lvalue パラメーターの場合、std::forward の呼び出し後にこのパラメーターを再利用すると、パラメーターに加えられた変更が、このパラメーターが渡される呼び出し側関数の引数に影響する可能性があります。

Polyspace 実装

std::forward の呼び出し後に転送されたオブジェクトが再利用される場合、Polyspace® はその呼び出しにフラグを設定します。また、Polyspace は、転送されたオブジェクトが再利用されているコード内の場所を強調表示します。

Polyspace は、std::forward の呼び出し後に到達できない分岐でその引数が再利用される場合、std::forward の呼び出しにフラグを設定しません。たとえばこのコード スニペットでは、std::forward が使用されている分岐にコードが入った後は、変数 t が再利用される分岐には到達できなくなります。

template<typename T>
void func(T&& t)
{
  T&& p = t;

  switch(t) { 
    case 0:
      p = std::forward<T>(t); 
      break;
    case 1:
      t--; //t reused 
      break;
  }
}

トラブルシューティング

ルール違反が想定されるものの、Polyspace から報告されない場合は、コーディング規約違反が想定どおりに表示されない理由の診断を参照してください。

すべて展開する

#include <cstdint>
#include <iostream>
#include <utility>

namespace myTemplates
{

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

template<typename T>
void f2(T&& t2, bool b)
{
    if (b) {
        f1(std::forward<T>(t2)); // Compliant
    } else {
        t2++;  // else branch not entered
    }

}


template<typename T>
void f3(T&& t3)
{
    T&& p = std::forward<T>(t3); // Non-compliant

    switch (t3) {                // t3 reused
    case 0:
        t3++;                    // t3 reused
        break;
    case 1:
        t3--;                    // t3 reused
        break;
    default:
        break;
    }
}


template<typename T>
void f4(T&& t4)
{
    --t4;

    f1(std::forward<T>(t4)); // Non-compliant

    t4++;                    // t4 reused

    f1(std::forward<T>(t4)); // Non-compliant and t4 reused

    t4--;                    // t4 reused
}


template<typename T>
void f5(T&& t5)
{
    f1(t5,                   // t5 reused
       std::forward<T>(t5)); // Non-compliant
}

}

void main(void)
{
    int i;

    myTemplates::f2(i, true);
    myTemplates::f3(i);
    myTemplates::f4(i);
    myTemplates::f5(i);

}

この例では、Polyspace は、呼び出し後に転送されたパラメーターを再利用する、すべての std::forward 呼び出しにフラグを設定します。テンプレート関数 f4 での std::forward の 2 番目の呼び出しが t4 パラメーターの再利用としてカウントされます。f2 には、このルールに対する違反はありません。t2 が再利用されている else 分岐に入ることはないためです。

チェック情報

グループ: 言語サポート ライブラリ
カテゴリ: Required、Automated

バージョン履歴

R2020b で導入