Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

overload resolution for function pointers with noexcept

Given the following two overloads

template<class T_ret, class... Args>
int test(T_ret (*func)(Args...)) { return 1; }

template<typename T>
int test(const T &lambda) { return 2; }

there is a difference in behaviour between MSVC and gcc /clang when passing a function with the noexcept specifier.

In the following example:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

void func() noexcept {}

int main()
{
    return test(&func);
}

gcc and clang take the second overload, while MSVC takes the first overload (https://godbolt.org/z/eah3r7E8r). A more specific overload adding the noexcept specifier is found by all compilers:

template<class T_ret, class... Args>
int test(T_ret (*func)(Args...) noexcept) { return 3; }

Which overload resolution is correct in this case?

>Solution :

That’s a matter of what C++ version you are using.

Before C++17 noexcept was not part of the function type or the function pointer type. Therefore both functions could take the argument without any type conversion and partial ordering of function templates would break the tie in overload resolution towards the first overload, which is more specialized (it accepts only function pointers, while the second overload accepts any type).

Since C++17 noexcept is part of the function type and the function pointer type and a conversion which removes the noexcept is a non-identity conversion. Your first overload has no noexcept qualifier on the function pointer type in the parameter and therefore requires this conversion, making it a worse choice in ranking of the conversion sequences than the identity conversion sequence required for the second overload.

MSVC is defaulting to some standard before C++17, while recent GCC are defaulting to C++17, hence the difference in your compiler explorer test. They agree if you actually set the version.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading