C++ [[nodiscard]] on Class and Enum Declarations
This article explains how the [[nodiscard]] attribute
behaves when applied directly to class, struct, or enumeration types in
C++. Introduced in C++17 and expanded in C++20, this feature allows
developers to enforce call-site handling of specific types across an
entire codebase. You will learn the mechanics of type-level application,
how it differs from function-level annotations, common use cases, and
how to suppress warnings when necessary.
How Type-Level
[[nodiscard]] Operates
When the [[nodiscard]] attribute is applied to the
declaration of a class, struct, or
enum, its warning behavior automatically propagates to any
function that returns that type by value. Rather than annotating every
individual function that returns a critical type, declaring the type
itself as [[nodiscard]] guarantees that the compiler warns
developers whenever an instance returned by value is discarded.
struct [[nodiscard]] ErrorCode {
int code;
};
ErrorCode processData() {
return ErrorCode{0};
}
int main() {
processData(); // Compiler warning: return value of type 'ErrorCode' declared with 'nodiscard' attribute discarded
ErrorCode err = processData(); // OK: return value is consumed
return 0;
}Application to Enumerations
Applying [[nodiscard]] to an enumeration is particularly
useful for status indicators, error codes, and operational results. Any
function that returns the annotated enumeration by value triggers a
compiler diagnostic if the caller ignores the result.
enum class [[nodiscard]] Status {
Success,
Failure,
Pending
};
Status checkStatus();
void run() {
checkStatus(); // Compiler warning: ignoring return value
}By-Value vs. References and Pointers
The standard specifies that [[nodiscard]] applied to a
type only takes effect when a function returns that type by
value. If a function returns a reference (T&,
const T&) or a pointer (T*) to a
[[nodiscard]] class or enumeration, the compiler will not
emit a warning if the return value is discarded.
struct [[nodiscard]] Resource {};
Resource createResource(); // Warns if discarded
Resource& getGlobalResource(); // Does NOT warn if discarded
Resource* findResource(); // Does NOT warn if discardedC++20 String Literals
Starting in C++20, [[nodiscard]] can include a string
literal to provide an explicit explanation for why the returned type
must not be ignored.
class [[nodiscard("Discarding this object results in an immediate resource leak.")]] ScopedLock {
// RAII lock implementation
};When a caller ignores a returned ScopedLock, the
compiler displays the custom message alongside the warning.
Suppressing the Warning
If an operation returns a [[nodiscard]] type and you
intentionally want to ignore the result, you can explicitly cast the
function call to void. This signals intent to both the
compiler and future maintainers, suppressing the warning cleanly:
(void)processData(); // OK: Explicitly discarded, no warning emitted