Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is knowledge about noexcept-ness supposed to be forwarded when passing around a function pointer?

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 noexceptness 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 noexceptness declaration is completely ignored?

Does the standard have to say something specific about this?

like image 304
Irfy Avatar asked Dec 22 '12 14:12

Irfy


2 Answers

Section 15.4.13 of the C++11 standard states that "an exception-specification is not considered part of a function's type".

like image 61
Vaughn Cato Avatar answered Oct 17 '22 10:10

Vaughn Cato


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);.

like image 40
M.M Avatar answered Oct 17 '22 10:10

M.M