最終更新日時(UTC):
が更新

履歴 編集

[[nodiscard]]をコンストラクタのオーバーロードごとに付加できるようにする(C++20)

概要

戻り値が使用されない場合に警告を出力させる[[nodiscard]]属性を、コンストラクタのオーバーロードに付加できるようにする。

C++17段階では、クラス定義に[[nodiscard]]属性を付加することはできた。しかし、デフォルトコンストラクタなどリソース確保しないコンストラクタは戻り値を無視しても無害であるため、リソース確保するコンストラクタのオーバーロードにのみ[[nodiscard]]属性を付加したい場合があり、そのようなユースケースをサポートする。

この変更はC++17に対する欠陥とみなされ、コンパイラはC++20対応としてではなくC++17段階からこの仕様を実装している可能性がある。

仕様

  • C++17までは「nodiscardが付加された (CV修飾を付加できる) クラスもしくは列挙型」をnodiscard-typeと呼んでいたが、C++20では「到達可能な宣言にnodiscardが付加された (CV修飾を付加できる) クラスもしくは列挙型」をnodiscard-typeと呼ぶよう変更
  • nodiscard宣言されたコンストラクタを使用して構築もしくは初期化したオブジェクトを明示的に型変換することは、「戻り値を無視しない呼び出し (nodiscard call)」と見なす
    • ただし、明示的にvoidにキャストする以外での、評価される可能性のある戻り値を無視しない呼び出しは推奨しない。このような場合に実装は警告を出力する必要がある

#include <fstream>

class File {
  std::ifstream file_;
public:
  // リソース確保しないコンストラクタ
  File() = default;

  // リソース確保するコンストラクタ
  [[nodiscard]]
  explicit File(const std::string& filename)
    : file_(filename) {}
};

int main() {
  File{};        // 警告なし
  File{"a.txt"}; // 警告 : File::File(const std::string&)コンストラクタの戻り値が無視されている
  static_cast<void>(File{"a.txt"}); // 警告なし
}

出力例

prog.cc: In function 'int main()':
prog.cc:17:15: warning: ignoring return value of 'File::File(const string&)', declared with attribute 'nodiscard' [-Wunused-result]
   17 |   File{"a.txt"}; // 警告 : File::File(const std::string&)コンストラクタの戻り値が無視されている
      |               ^
prog.cc:11:12: note: declared here
   11 |   explicit File(const std::string& filename)
      |            ^~~~

関連項目

参照