I have written the following code to test noexcept
propagation across function calls, and it seems that it doesn't work as I would have thought. In GCC 4.7.2, A function can effectively be tested against being noexcept
only directly or when passed as a template specialization argument; but not when passed as an argument to a templated function, or as a function pointer to a normal function -- even when that function declares its formal parameter as being noexcept
. Here's the code:
#include <iostream>
#define test(f) \
std::cout << __func__ << ": " #f " is " \
<< (noexcept(f()) ? "" : "not ") \
<< "noexcept\n";
template <void(*f)()>
static inline void test0() {
test(f);
}
template <typename F>
static inline void test1(F f) {
test(f);
}
static inline void test2(void(*f)()) {
test(f);
}
static inline void test3(void(*f)()noexcept) {
test(f);
}
void f1() {}
void f2() noexcept {}
int main() {
test(f1);
test(f2);
test0<f1>();
test0<f2>();
test1(f1);
test1(f2);
test2(f1);
test2(f2);
test3(f1);
test3(f2);
return 0;
}
And here's output:
main: f1 is not noexcept main: f2 is noexcept test0: f is not noexcept test0: f is noexcept test1: f is not noexcept test1: f is not noexcept test2: f is not noexcept test2: f is not noexcept test3: f is not noexcept test3: f is not noexcept
Why is noexcept
ness not propagated in other cases? In case of test1
, the whole function is "instantiated" with the proper type of F
, the compiler surely knows at that time whether F is a noexcept
function. Why is it possible to write test3
the way I wrote it, when the noexcept
ness declaration is completely ignored?
Does the standard have to say something specific about this?
Section 15.4.13 of the C++11 standard states that "an exception-specification is not considered part of a function's type".
In C++17, noexcept
is finally added to the type system. A pointer to non-noexcept
function cannot be implicitly converted to pointer to noexcept
function. (But the other way around is permitted).
clang 3.9.0 with -std=c++1z
, and g++ 7.0 with -std=c++17
, reject the line test3(f1);
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With