- cpp20[meta cpp]
戻り値が使用されない場合に警告を出力させる[[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)
| ^~~~