Last updated:2026-10-12
C++17 [[nodiscard]] Attribute¶
Since the [[nodiscard]] attribute was introduced in C++17, we have had a more powerful tool for marking function return values that should not be ignored at the call site. In this article we will take a deep dive into how to use [[nodiscard]] and watch out for some potential pitfalls.
What is [[nodiscard]]?¶
[[nodiscard]] is a function attribute that tells the compiler that the return value of a function should not be ignored. This is especially useful for functions that rely on their return value, such as predicate functions or factory functions.
How to use [[nodiscard]]?¶
It is possible to use [[nodiscard]] on classes, constructors, and enums. Here are some examples:
class [[nodiscard]] A {};
class B {
public:
[[nodiscard]] B() = default;
};
enum class [[nodiscard]] State {
Default,
Foo,
Bar
};
In the examples above, the compiler will issue a warning whenever the return value is ignored, which helps us catch potential bugs early.
Watch out: pitfalls of [[nodiscard]]¶
Although [[nodiscard]] can effectively prevent return values from being ignored unintentionally, we need to be aware of some potential pitfalls. A common pitfall is a [[nodiscard]] function that returns a scope-guard-like object in order to perform cleanup at the end of the scope (for example, committing a transaction).
[[nodiscard]] ScopeGuard createScopeGuard() {
// Implementation of a scope guard
}
// 在这里,用户可以选择忽略返回值,导致作用域立即销毁,从而失去清理效果
std::ignore = createScopeGuard();
Although [[nodiscard]] indicates that the return value of the function should not be ignored, the user can still explicitly discard the return value by means such as std::ignore, thereby bypassing the cleanup.
Complete example¶
#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
}
Related Topics¶
- C++17 std::string_view | C++那些事
- C++17 PMR Memory Resources | C++那些事
- C++17 Seventeen Advanced Features | C++那些事
- C++17 Class Template Argument Deduction CTAD | C++那些事
- C++17 optional_ref | C++那些事
- C++17 std::variant | C++那些事
- C++17 Structured Bindings | C++那些事
- C++17 Template auto Deduction | C++那些事
- C++17 Variable Templates | C++那些事