Since C++17, exception specifications have become a part of a function type. This implies that these two functions, for example, have different
types:
void first() noexcept;
void second();
Making exception specifications part of the type will, for the right reason, break code where a function that throws an exception is provided in a
context where noexcept
function is expected.
It is important to note that, like it is not allowed to overload based on the return type, it is also not allowed to overload based on the
exception specifications.
This rule will trigger on code that will stop compiling starting C++17, and on explicit casts that add noexcept
to a type.
Noncompliant code example
template<typename T>
void callF1(T t1, T t2) {
t1();
t2();
}
void f1();
void f1NoExcept() noexcept;
int main() {
callF1(f1, f1NoExcept); // Noncompliant, f1 and f1NoExcept have different types
std::function<void() noexcept> fptr1 = f1; // Noncompliant
void (*fptr2)() noexcept = f1; // Noncompliant
void (*fptr3)() noexcept = (void (*)() noexcept) f1; // Noncompliant, it works even in c++17
}
Compliant solution
template<typename T1, typename T2>
void callF1(T1 t1, T2 t2) {
t1();
t2();
}
void f1();
void f1NoExcept() noexcept;
int main() {
callF1(f1, f1NoExcept); // Compliant
std::function<void() noexcept> fptr1 = f1NoExcept; // Compliant
void (*fptr2)() = f1; // Compliant
}