最終更新:2026-10-12
C++17 [[nodiscard]] 属性¶
C++17で[[nodiscard]]属性が導入されて以来、私たちはAPIを書く際に、呼び出し時に無視すべきでない関数の戻り値をマークするための、より強力なツールを手に入れました。本記事では[[nodiscard]]の使い方を深く掘り下げ、いくつかの潜在的な罠についても見ていきます。
[[nodiscard]]とは何か?¶
[[nodiscard]]は関数属性の一種で、関数の戻り値を無視すべきではないことをコンパイラに伝えます。これは、述語関数やファクトリ関数など、戻り値に依存する関数で特に有用です。
[[nodiscard]]の使い方¶
[[nodiscard]]は、クラス、コンストラクタ、列挙型に対して使うこともできます。以下にいくつか例を示します:
class [[nodiscard]] A {};
class B {
public:
[[nodiscard]] B() = default;
};
enum class [[nodiscard]] State {
Default,
Foo,
Bar
};
上の例では、戻り値が無視されたときにコンパイラが警告を発するため、潜在的なバグを早期に発見する助けになります。
注意:[[nodiscard]]の罠¶
[[nodiscard]]は戻り値がうっかり無視されるのを効果的に防げますが、いくつかの潜在的な罠に注意する必要があります。よくある罠は、[[nodiscard]]を付けた関数が、スコープ終了時にクリーンアップ操作(トランザクションのコミットなど)を実行する、スコープガードのようなオブジェクトを返す場合です。
[[nodiscard]] ScopeGuard createScopeGuard() {
// Implementation of a scope guard
}
// 在这里,用户可以选择忽略返回值,导致作用域立即销毁,从而失去清理效果
std::ignore = createScopeGuard();
[[nodiscard]]は関数の戻り値を無視すべきでないことを示しますが、ユーザーはstd::ignoreなどの手段を使って明示的に戻り値を無視し、クリーンアップ操作を回避できてしまいます。
完全な例¶
#include <tuple> // std::ignore
class [[nodiscard]] A {};
class B {
public:
[[nodiscard]] bool isOk() const { return true; }
};
// no need for nodiscard, A is nodiscard
A foo() {
return A();
}
// B is not nodiscard, mark it explicitly
[[nodiscard]] B bar() {
return B();
}
int main()
{
foo(); // warning: ignoring temporary created by a constructor declared with 'nodiscard' attribute
bar(); // warning
std::ignore = foo(); // ok
auto b = bar(); // ok
b.isOk(); // warning
if (b.isOk()) {} // ok
}
関連トピック¶
- C++17 std::string_view | C++那些事
- C++17 PMR メモリリソース | C++那些事
- C++17 17の高度な機能 | C++那些事
- C++17 クラステンプレートのテンプレート引数推論 CTAD | C++那些事
- C++17 optional_ref | C++那些事
- C++17 std::variant | C++那些事
- C++17 構造化束縛 | C++那些事
- C++17 テンプレート auto 推論 | C++那些事
- C++17 変数テンプレート | C++那些事