戻り値を無視させない[[nodiscard]]属性
C++ のクラスにはたまに使い方が少し曖昧なメンバー関数があります。
例えば、List
というコンテナがあって、reverse()
という要素の並びが逆になっている新しいList
を返すメンバー関数があるとしましょう。
List reverse() const;
でも関数名だけを見て、以下のようにそのインスタンス自体の要素の並びを逆にする関数だと勘違いされて、間違った使い方されるかもしれないです。
List list{1, 2, 3};
list.reverse();
std::cout << list << std::endl; // list の要素は変わっていない
このような戻り値を無視してはいけない関数に[[nodiscard]]
という C++17 で追加された属性を付けると、
[[nodiscard]] List reverse() const;
無視した場合は以下の警告が出るようになります。
"warning C4834: discarding return value of function with 'nodiscard' attribute"
本当はエラーになるようにして欲しかったんですけどね😇
でもこの属性はどこまで使った方がいいのでしょうか?
戻り値が任意の場合は付けない方がいいのはもちろんですが、戻り値が大事な関数全部に付けるのもやりすぎな気がします。これに関するルールや決まりはないのですが、参考に標準ライブラリでの使い方を見てみましょう。
[[nodiscard]]
は C++17 で追加されてから、標準ライブラリでも使われるようになりました。 大体のコンパイラーの実装では殆どの戻り値がある関数に付けられていますが、C++17の仕様では付けられた関数の数が意外と少ないです。
理由が関数名にあります。empty
は「空」という意味の形容詞でもありますが、「空にする」という意味の動詞でもあります。clear()
のようにコンテナを空にすると勘違いされる可能性があるということで付けられて、size()
とlength()
の場合は誤解の余地がないため付けられていないとか。
要するに、間違った使い方される恐れがある関数に付ける、でいかがでしょうか?
Discussion