2020-08-13追記:C++17で言語仕様が調整され、constexpr関数であってもnoexceptは特別扱いされなくなった。詳細は c++ - `noexcept` behavior of `constexpr` functions - Stack Overflow 参照のこと。
定数式(constant expression)中で呼び出すconstexpr関数は、noexcept指定がされているかのように振る舞う。ただし未定義constexpr関数の呼び出しや、非定数式コンテキストからのconstepxr関数呼び出しは、同ルールの適用外となる。
// C++14 constexpr int f() { return 0; } constexpr int g(); // 宣言のみ static_assert( noexcept(f()), "noexcept(f()) shall be true"); static_assert(!noexcept(g()), "noexcept(g()) shall be false"); constexpr int h(bool b) { return b ? 0 : throw 42; } static_assert( noexcept(h(true)), "noexcept(h(T)) shall be true"); static_assert(!noexcept(h(false)), "noexcept(h(F)) shall be false"); #include <iostream> int main() { std::cout << std::boolalpha; std::cout << noexcept(h(true)); // true bool b = true; std::cout << noexcept(h(b)); // false }
上記コードはgccだと期待通り動作するが、Clangは3.6.0現在でも未対応のためコンパイルエラーとなる。
C++11 5.3.7/p3, 5.19/p2より一部引用(下線部は強調)。
3 The result of the
noexcept
operator isfalse
if in a potentially-evaluated context the expression would contain
- a potentially evaluated call to a function, member function, function pointer, or member function pointer that does not have a non-throwing exception-specification (15.4), unless the call is a constant expression (5.19),
- (snip)
Otherwise, the result is
true
.
2 A conditional-expression is a core constant expression unless it involves one of the following as a potentially evaluated subexpression (3.2), but subexpressions of logical AND (5.14), logical OR (5.15), and conditional (5.16) operations that are not evaluated are not considered [Note: An overloaded operator invokes a function. -- end note]:
- (snip)
- an invocation of an undefined
constexpr
function or an undefinedconstexpr
constructor outside the definition of aconstexpr
function or aconstexpr
constructor;- (snip)
- a throw-expression (15.1).
関連URL
- C++ Standard Core Language Defect Reports, #1129 Default nothrow for constexpr functions
- Non-constant constant-expressions in C++
- c++ - Is is_constexpr possible in C++11? - Stack Overflow