97 lines
5.1 KiB
Markdown
97 lines
5.1 KiB
Markdown
[dcl.attr.nodiscard]
|
||
|
||
# 9 Declarations [[dcl]](./#dcl)
|
||
|
||
## 9.13 Attributes [[dcl.attr]](dcl.attr#nodiscard)
|
||
|
||
### 9.13.9 Nodiscard attribute [dcl.attr.nodiscard]
|
||
|
||
[1](#1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L10007)
|
||
|
||
The [*attribute-token*](dcl.attr.grammar#nt:attribute-token "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") nodiscard may be applied to a function or a lambda call operator or
|
||
to the declaration of a class or enumeration[.](#1.sentence-1)
|
||
|
||
An [*attribute-argument-clause*](dcl.attr.grammar#nt:attribute-argument-clause "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") may be present
|
||
and, if present, shall have the form:
|
||
|
||
( [*unevaluated-string*](lex.string.uneval#nt:unevaluated-string "5.13.6 Unevaluated strings [lex.string.uneval]") )
|
||
|
||
[2](#2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L10017)
|
||
|
||
A name or entity declared without the nodiscard attribute
|
||
can later be redeclared with the attribute and vice-versa[.](#2.sentence-1)
|
||
|
||
[*Note [1](#note-1)*:
|
||
|
||
Thus, an entity initially declared without the attribute
|
||
can be marked as nodiscard by a subsequent redeclaration[.](#2.sentence-2)
|
||
|
||
However, after an entity is marked as nodiscard,
|
||
later redeclarations do not remove the nodiscard from the entity[.](#2.sentence-3)
|
||
|
||
â *end note*]
|
||
|
||
Redeclarations using different forms of the attribute
|
||
(with or without the [*attribute-argument-clause*](dcl.attr.grammar#nt:attribute-argument-clause "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") or with different [*attribute-argument-clause*](dcl.attr.grammar#nt:attribute-argument-clause "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")*s*)
|
||
are allowed[.](#2.sentence-4)
|
||
|
||
[3](#3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L10033)
|
||
|
||
A [*nodiscard type*](#def:type,nodiscard "9.13.9 Nodiscard attribute [dcl.attr.nodiscard]") is
|
||
a (possibly cv-qualified) class or enumeration type
|
||
marked nodiscard in a reachable declaration[.](#3.sentence-1)
|
||
|
||
A [*nodiscard call*](#def:call,nodiscard "9.13.9 Nodiscard attribute [dcl.attr.nodiscard]") is either
|
||
|
||
- [(3.1)](#3.1)
|
||
|
||
a function call expression ([[expr.call]](expr.call "7.6.1.3 Function call"))
|
||
that calls a function declared nodiscard in a reachable declaration or
|
||
whose return type is a nodiscard type, or
|
||
|
||
- [(3.2)](#3.2)
|
||
|
||
an explicit type
|
||
conversion ([[expr.type.conv]](expr.type.conv "7.6.1.4 Explicit type conversion (functional notation)"), [[expr.static.cast]](expr.static.cast "7.6.1.9 Static cast"), [[expr.cast]](expr.cast "7.6.3 Explicit type conversion (cast notation)"))
|
||
that constructs an object through
|
||
a constructor declared nodiscard in a reachable declaration, or
|
||
that initializes an object of a nodiscard type[.](#3.sentence-2)
|
||
|
||
[4](#4)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L10051)
|
||
|
||
*Recommended practice*: Appearance of a nodiscard call as
|
||
a potentially-evaluated discarded-value expression ([[expr.prop]](expr.prop "7.2 Properties of expressions"))
|
||
of non-void type
|
||
is discouraged unless explicitly cast to void[.](#4.sentence-1)
|
||
|
||
Implementations should issue a warning in such cases[.](#4.sentence-2)
|
||
|
||
The value of
|
||
a [*has-attribute-expression*](cpp.cond#nt:has-attribute-expression "15.2 Conditional inclusion [cpp.cond]") for the nodiscard attribute
|
||
should be 0 unless the implementation can issue such warnings[.](#4.sentence-3)
|
||
|
||
[*Note [2](#note-2)*:
|
||
|
||
This is typically because discarding the return value
|
||
of a nodiscard call has surprising consequences[.](#4.sentence-4)
|
||
|
||
â *end note*]
|
||
|
||
The [*unevaluated-string*](lex.string.uneval#nt:unevaluated-string "5.13.6 Unevaluated strings [lex.string.uneval]") in a nodiscard [*attribute-argument-clause*](dcl.attr.grammar#nt:attribute-argument-clause "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") should be used in the message of the warning
|
||
as the rationale for why the result should not be discarded[.](#4.sentence-5)
|
||
|
||
[5](#5)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L10070)
|
||
|
||
[*Example [1](#example-1)*: struct [[nodiscard]] my_scopeguard { /* ... */ };struct my_unique { my_unique() = default; // does not acquire resource[[nodiscard]] my_unique(int fd) { /* ... */ } // acquires resource~my_unique() noexcept { /* ... */ } // releases resource, if any/* ... */};struct [[nodiscard]] error_info { /* ... */ };
|
||
error_info enable_missile_safety_mode();void launch_missiles();void test_missiles() { my_scopeguard(); // warning encouraged(void)my_scopeguard(), // warning not encouraged, cast to void launch_missiles(); // comma operator, statement continues my_unique(42); // warning encouraged my_unique(); // warning not encouraged enable_missile_safety_mode(); // warning encouraged launch_missiles();} error_info &foo();void f() { foo(); } // warning not encouraged: not a nodiscard call, because neither// the (reference) return type nor the function is declared nodiscard â *end example*]
|