On C++ Primer on noexcept
exception specification, it is said that a pointer to a function that may throw Implicitly (defined without exception specification e.g: void(*p)();
) or explicitly (void(*p)() noexcept(false);
) may point to any function even to a non-throwing function.
On the other hand a function pointer which may not throw (noexcept
e.g void(*p) noexcept;
) can only point to a function that won't throw.
I found that very logical because the first pointer it is OK to point to a non-throwing function from a throwing function pointer and the second too is so logical.
I've tried this to understand more:
void func1(){ // may throw
std::cout << "func1()\n";
}
void func2() noexcept(false){ // may throw
std::cout << "func2()\n";
}
void func3() noexcept(true){ // won't throw
std::cout << "func3()\n";
}
void func4() noexcept{ // won't throw
std::cout << "func4()\n";
}
int main(int argc, char* argv[]){
void(*pFn1)();
pFn1 = func1; // OK
pFn1 = func2; // OK
pFn1 = func3; // OK
pFn1 = func4; // OK
void(*pFn2)() noexcept(false);
pFn2 = func1; // OK
pFn2 = func2; // OK
pFn2 = func3; // OK
pFn2 = func4; // OK
void(*pFn3)() noexcept(true);
pFn3 = func1; // Error on C++ 17 and above. OK on C++11 and 14
pFn3 = func2; // Error on C++ 17 and above. OK on C++11 and 14
pFn3 = func3; // OK
pFn3 = func4; // OK
void(*pFn4)() noexcept(true);
pFn4 = func1; // Error on C++ 17 and above. OK on C++11 and 14
pFn4 = func2; // Error on C++ 17 and above. OK on C++11 and 14
pFn4 = func3; // OK
pFn4 = func4; // OK
std::cout << '\n';
}
-std=c++17
, -std=c++2a
it works as it should so I get the errors as I've written in the lines comments. But when I compile against -std=c++11
, -std=c++14
I get them all work and the compiler doesn't complain?!Does this mean the standard has changed? Thank you!
Any pointer can refer to any location in memory, so technically the statement is correct. With that said, you need to be careful when reinterpreting pointer types. A pointer basically has two pieces of information: a memory location, and the type it expects to find there. The memory location could be anything.
What will we not do with function pointers? Explanation: As it is used to execute a block of code, So we will not allocate or deallocate memory.
C++ allows you to pass a pointer to a function. To do so, simply declare the function parameter as a pointer type.
When an exception is thrown from a function that is declared noexcept or noexcept(true) , std::terminate is invoked. When an exception is thrown from a function declared as throw() in /std:c++14 mode, the result is undefined behavior. No specific function is invoked.
It's ill-formed in C++17 because the noexcept
is part of the type system, and there is no conversion from a pointer to a potentially-throwing function to a pointer to a non-throwing function.
Before C++17 the relevant rule is [except.spec] p5:
A similar restriction applies to assignment to and initialization of pointers to functions, pointers to member functions, and references to functions: the target entity shall allow at least the exceptions allowed by the source value in the assignment or initialization.
So although the noexcept
isn't part of the type system, the OP's assignments are ill-formed.
G++ does not give an error for the example in p5:
class A { /* ... */ };
void (*pf1)(); // no exception specification
void (*pf2)() throw(A);
void f() {
pf1 = pf2; // OK: pf1 is less restrictive
pf2 = pf1; // error: pf2 is more restrictive
}
That should be ill-formed in C++98/11/14.
The equivalent with a noexcept-specifier would be:
class A { /* ... */ };
void (*pf1)(); // no exception specification
void (*pf2)() noexcept;
void f() {
pf1 = pf2; // OK: pf1 is less restrictive
pf2 = pf1; // error: pf2 is more restrictive
}
G++ doesn't reject this in 98/11/14, only C++17 and up.
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