メインコンテンツ

AUTOSAR C++14 Rule A12-8-7

Assignment operators should be declared with the ref-qualifier &

説明

ルール定義

Assignment operators should be declared with the ref-qualifier &.

根拠

ref 修飾子を使用して、lvalue または rvalue に関数と演算子のどちらかを適用するかを指定できます。lvalue に適用される関数または演算子には ref 修飾子 & が付加されます。rvalue に適用される関数または演算子には宣言の最後に ref 修飾子 && が付加されます。

C++ の組み込み代入演算子は、入力パラメーターとして lvalue のみを受け入れます。ユーザー定義の代入演算子が入力パラメーターとして rvalue と lvalue の両方を取る場合、それは混乱の原因となり、エラーを引き起こす可能性があります。クラス obj 用のユーザー定義の代入演算子が入力パラメーターとして rvalue と lvalue の両方を受け入れる次のコードについて考えます。

class obj{
	obj& operator=(Obj const&){
		//...
		return *this;
	}
	//...
};

int main(){
	int i,j,k;
	obj a,b,c;

	if((i+j)=k) // compilation error
	//...
	if((a+b)=c) // silent error
	//...
}

  • 最初の if ステートメントでは、等号演算子 (==) が誤記により代入演算子 (=) と記述されています。int 用の組み込み代入演算子は入力として rvalue を受け入れないため、ステートメント (i+j) = k はコンパイル エラーを引き起こします。

  • 2 番目の if ステートメントの条件に同様のエラーが含まれています。クラス obj 用のユーザー定義の代入演算子は入力として rvalue と lvalue の両方を受け入れるため、ステートメント (a+b) = c はエラーなしでコンパイルされます。if ブロックは予期せず実行されるため、サイレント バグにつながります。

エラーと混乱を避けるには、ref 修飾子 & を宣言に追加することによって、代入演算子が入力パラメーターとして lvalue のみを取るように指定します。

Polyspace 実装

Polyspace® は、以下の場合のユーザー定義の代入、複合代入、インクリメント、およびデクリメント演算子にフラグを設定します。

  • 宣言に ref 修飾子 & が含まれていない。

  • クラスのメンバー関数である。

  • = delete として宣言されていない。

ref 修飾子は非静的メンバー関数にしか適用できないため、このルールは非メンバー代入演算子には適用されません。

トラブルシューティング

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

すべて展開する

この例では、宣言で ref 修飾子 & を指定しなかった場合に、Polyspace が代入演算子とインクリメントまたはデクリメント演算子にどのようにフラグを設定するかを示します。

#include<cstdint>
class Obj
{
public:
	Obj() = default;
	Obj& operator=(Obj const&) & = default; //Compliant    
	Obj& operator=(Obj&&) & = default;      //Compliant    
	Obj& operator++() & noexcept;           //Compliant    
	Obj& operator--()  noexcept;            //Noncompliant 
	Obj& operator<<=(Obj const&) noexcept;  //Noncompliant   
	Obj& operator>>=(Obj const&) & noexcept;//Compliant   
	Obj& operator+=(Obj const&)&;           //Compliant
	Obj& operator-=(Obj const&);            //Noncompliant
	Obj& operator*=(Obj const&)= delete;    //Compliant
	Obj& operator+(Obj const&)&;            //Compliant  
};

Obj& operator|=(Obj& f,const std::int32_t i) // Rule does not apply 
{
	return f;
}

Obj& Obj::operator+=(Obj const&) &  // Polyspace flags the declaration 
{
	return *this;
}
Obj F1() noexcept
{
	return Obj{};
}
int main()
{
	Obj c;
	//F1() += c; // Compilation Error
	//F1() = c; // Compilation Error
	F1() -= c; // Silent Bug
}

main() では、代入演算子の +=-=、および = が rvlaue 入力と一緒に使用されます。演算子の +== の宣言で ref 修飾子 & が指定されているため、これらの演算子と一緒に rvalue 入力を使用するとコンパイル エラーになります。演算子 -= は、ref 修飾子 & なしで宣言されます。この演算子と一緒に rvalue 入力を使用すると、サイレント バグが発生します。

  • Polyspace は、宣言で ref 修飾子 & が指定されていない、メンバー代入演算子、インクリメント演算子、およびデクリメント演算子の使用にフラグを設定します。

  • メンバー代入演算子がクラス内で ref 修飾子 & なしで宣言され、クラス以外の場所で定義されている場合は、Polyspace がその宣言にフラグを設定します。

  • Polyspace は、ref 修飾子 & のない非メンバー演算子にはフラグを設定しません。これは、このルールが非静的メンバー関数にしか適用されないためです。

  • Polyspace は、削除済みの演算子にはフラグを設定しません。これは、削除済みの演算子に対して ref 修飾子 & を使用してもコードに影響しないためです。

チェック情報

グループ: 特殊なメンバー関数
カテゴリ: Advisory、Automated

バージョン履歴

R2020b で導入