Difference between revisions of "cpp/language/noexcept"
m (→Keywords: −usage −rev) |
|||
(33 intermediate revisions by 14 users not shown) | |||
Line 1: | Line 1: | ||
− | {{title|noexcept operator {{mark since c++11}}}} | + | {{title|{{tt|noexcept}} operator {{mark since c++11}}}} |
− | {{cpp/language/navbar}} | + | {{cpp/language/expressions/exceptions/navbar}} |
− | The {{ | + | The {{c/core|noexcept}} operator performs a compile-time check that returns {{c|true}} if an expression is declared to not throw any exceptions. |
− | It can be used within a function template's {{rlp| | + | It can be used within a function template's {{rlp|noexcept spec|{{c/core|noexcept}} specifier}} to declare that the function will throw exceptions for some types but not others. |
===Syntax=== | ===Syntax=== | ||
+ | {{sdsc begin}} | ||
+ | {{sdsc|{{ttb|noexcept(}} {{spar|expression}} {{ttb|)}}}} | ||
+ | {{sdsc end}} | ||
− | {{ | + | Returns a {{rlpsd|value category#prvalue}} of type {{c/core|bool}}. The result is {{c|true}} if {{rev inl|until=c++17|the set of {{rlp|except spec|potential exceptions}} of the {{spar|expression}} is empty}}{{rev inl|since=c++17|{{spar|expression}} is specified to be {{rlp|noexcept spec|non-throwing}}}}, and {{c|false}} otherwise. |
− | {{ | + | |
− | {{ | + | |
− | + | {{spar|expression}} is an {{rlp|expressions#Potentially-evaluated expressions|unevaluated operand}}. | |
− | = | + | {{rrev|since=c++17| |
+ | If {{spar|expression}} is a prvalue, {{rlpsd|implicit conversion#Temporary materialization}} is applied. | ||
+ | }} | ||
− | + | ===Notes=== | |
+ | Even if {{c|noexcept(expr)}} is {{c|true}}, an evaluation of {{c|expr}} may still throw as the result of encountering undefined behavior. | ||
− | + | {{rrev|since=c++17| | |
− | + | If {{spar|expression}} is of a class type or (possibly multidimensional) array thereof, temporary materialization requires the destructor be non-deleted and accessible. | |
− | + | }} | |
− | + | ||
− | + | ||
− | + | ||
===Keywords=== | ===Keywords=== | ||
− | + | {{ltt|cpp/keyword/noexcept}} | |
− | {{ltt|cpp/ | + | |
===Example=== | ===Example=== | ||
{{example | {{example | ||
− | + | |code= | |
− | + | #include <iostream> | |
− | + | #include <utility> | |
− | + | #include <vector> | |
− | + | ||
− | } | + | void may_throw(); |
+ | void no_throw() noexcept; | ||
+ | auto lmay_throw = []{}; | ||
+ | auto lno_throw = []() noexcept {}; | ||
+ | |||
+ | class T | ||
+ | { | ||
+ | public: | ||
+ | ~T(){} // dtor prevents move ctor | ||
+ | // copy ctor is noexcept | ||
+ | }; | ||
+ | |||
+ | class U | ||
+ | { | ||
+ | public: | ||
+ | ~U(){} // dtor prevents move ctor | ||
+ | // copy ctor is noexcept(false) | ||
+ | std::vector<int> v; | ||
+ | }; | ||
+ | |||
+ | class V | ||
+ | { | ||
+ | public: | ||
+ | std::vector<int> v; | ||
+ | }; | ||
+ | |||
+ | int main() | ||
+ | { | ||
+ | T t; | ||
+ | U u; | ||
+ | V v; | ||
+ | |||
+ | std::cout << std::boolalpha << | ||
+ | "may_throw() is noexcept(" << noexcept(may_throw()) << ")\n" | ||
+ | "no_throw() is noexcept(" << noexcept(no_throw()) << ")\n" | ||
+ | "lmay_throw() is noexcept(" << noexcept(lmay_throw()) << ")\n" | ||
+ | "lno_throw() is noexcept(" << noexcept(lno_throw()) << ")\n" | ||
+ | "~T() is noexcept(" << noexcept(std::declval<T>().~T()) << ")\n" | ||
+ | // note: the following tests also require that ~T() is noexcept because | ||
+ | // the expression within noexcept constructs and destroys a temporary | ||
+ | "T(rvalue T) is noexcept(" << noexcept(T(std::declval<T>())) << ")\n" | ||
+ | "T(lvalue T) is noexcept(" << noexcept(T(t)) << ")\n" | ||
+ | "U(rvalue U) is noexcept(" << noexcept(U(std::declval<U>())) << ")\n" | ||
+ | "U(lvalue U) is noexcept(" << noexcept(U(u)) << ")\n" | ||
+ | "V(rvalue V) is noexcept(" << noexcept(V(std::declval<V>())) << ")\n" | ||
+ | "V(lvalue V) is noexcept(" << noexcept(V(v)) << ")\n"; | ||
+ | } | ||
+ | |output= | ||
+ | may_throw() is noexcept(false) | ||
+ | no_throw() is noexcept(true) | ||
+ | lmay_throw() is noexcept(false) | ||
+ | lno_throw() is noexcept(true) | ||
+ | ~T() is noexcept(true) | ||
+ | T(rvalue T) is noexcept(true) | ||
+ | T(lvalue T) is noexcept(true) | ||
+ | U(rvalue U) is noexcept(false) | ||
+ | U(lvalue U) is noexcept(false) | ||
+ | V(rvalue V) is noexcept(true) | ||
+ | V(lvalue V) is noexcept(false) | ||
}} | }} | ||
+ | |||
+ | ===Defect reports=== | ||
+ | {{dr list begin}} | ||
+ | {{dr list item|wg=cwg|dr=2722|std=C++17|before=it was unclear whether temporary materialization<br>is applied if {{spar|expression}} is a prvalue|after=it is applied<br>in this case}} | ||
+ | {{dr list item|wg=cwg|dr=2792|std=C++11|before=the {{c/core|noexcept}} operator was required to determine whether exceptions<br>may be thrown in the case of encountering undefined behavior|after=not required}} | ||
+ | {{dr list end}} | ||
===See also=== | ===See also=== | ||
− | {{ | + | {{dsc begin}} |
− | {{ | + | {{dsc inc|cpp/language/dsc noexcept spec}} |
− | {{ | + | {{dsc inc|cpp/language/dsc except spec}} |
− | {{ | + | {{dsc end}} |
− | + | {{langlinks|de|es|fr|it|ja|pt|ru|zh}} | |
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + |
Latest revision as of 15:44, 12 August 2024
The noexcept operator performs a compile-time check that returns true if an expression is declared to not throw any exceptions.
It can be used within a function template's noexcept specifier to declare that the function will throw exceptions for some types but not others.
Contents |
[edit] Syntax
noexcept( expression )
|
|||||||||
Returns a prvalue of type bool. The result is true if the set of potential exceptions of the expression is empty(until C++17)expression is specified to be non-throwing(since C++17), and false otherwise.
expression is an unevaluated operand.
If expression is a prvalue, temporary materialization is applied. |
(since C++17) |
[edit] Notes
Even if noexcept(expr) is true, an evaluation of expr may still throw as the result of encountering undefined behavior.
If expression is of a class type or (possibly multidimensional) array thereof, temporary materialization requires the destructor be non-deleted and accessible. |
(since C++17) |
[edit] Keywords
[edit] Example
#include <iostream> #include <utility> #include <vector> void may_throw(); void no_throw() noexcept; auto lmay_throw = []{}; auto lno_throw = []() noexcept {}; class T { public: ~T(){} // dtor prevents move ctor // copy ctor is noexcept }; class U { public: ~U(){} // dtor prevents move ctor // copy ctor is noexcept(false) std::vector<int> v; }; class V { public: std::vector<int> v; }; int main() { T t; U u; V v; std::cout << std::boolalpha << "may_throw() is noexcept(" << noexcept(may_throw()) << ")\n" "no_throw() is noexcept(" << noexcept(no_throw()) << ")\n" "lmay_throw() is noexcept(" << noexcept(lmay_throw()) << ")\n" "lno_throw() is noexcept(" << noexcept(lno_throw()) << ")\n" "~T() is noexcept(" << noexcept(std::declval<T>().~T()) << ")\n" // note: the following tests also require that ~T() is noexcept because // the expression within noexcept constructs and destroys a temporary "T(rvalue T) is noexcept(" << noexcept(T(std::declval<T>())) << ")\n" "T(lvalue T) is noexcept(" << noexcept(T(t)) << ")\n" "U(rvalue U) is noexcept(" << noexcept(U(std::declval<U>())) << ")\n" "U(lvalue U) is noexcept(" << noexcept(U(u)) << ")\n" "V(rvalue V) is noexcept(" << noexcept(V(std::declval<V>())) << ")\n" "V(lvalue V) is noexcept(" << noexcept(V(v)) << ")\n"; }
Output:
may_throw() is noexcept(false) no_throw() is noexcept(true) lmay_throw() is noexcept(false) lno_throw() is noexcept(true) ~T() is noexcept(true) T(rvalue T) is noexcept(true) T(lvalue T) is noexcept(true) U(rvalue U) is noexcept(false) U(lvalue U) is noexcept(false) V(rvalue V) is noexcept(true) V(lvalue V) is noexcept(false)
[edit] Defect reports
The following behavior-changing defect reports were applied retroactively to previously published C++ standards.
DR | Applied to | Behavior as published | Correct behavior |
---|---|---|---|
CWG 2722 | C++17 | it was unclear whether temporary materialization is applied if expression is a prvalue |
it is applied in this case |
CWG 2792 | C++11 | the noexcept operator was required to determine whether exceptions may be thrown in the case of encountering undefined behavior |
not required |
[edit] See also
noexcept specifier(C++11)
|
specifies whether a function could throw exceptions |
Dynamic exception specification(until C++17) | specifies what exceptions are thrown by a function (deprecated in C++11) |