I have a trait to determine the class of a member function pointer.
In GCC12, it works for both const and const noexcept function pointers.
In GCC13, it no longer works. Clang 16 and MSVC agree with GCC12. If I add a noexcept specialisation, it fixes GCC12, and breaks GCC12/Clang/MSVC.
Is this behaviour specified in the C++ Standard, or is this a GCC bug?
If this is expected behaviour, how can I support both GCC12 and GCC13?
#include <type_traits>
template <auto>
struct get_class;
template <typename Ret, typename Klass, typename... Args, Ret (Klass::*FN)(Args...) const>
struct get_class<FN> : public std::type_identity<Klass>
{};
// Uncomment this to fix GCC13, and break everyone else...
//template <typename Ret, typename Klass, typename... Args, Ret (Klass::*FN)(Args...) const noexcept>
//struct get_class<FN> : public std::type_identity<Klass>
//{};
class MyClass {
public:
int func1() const noexcept {return 0;}
int func2() const {return 0;}
};
int main(){
[[maybe_unused]]get_class<&MyClass::func1>::type x = MyClass{};
[[maybe_unused]]get_class<&MyClass::func2>::type y = MyClass{};
}
Live example: https://godbolt.org/z/YGv8hxPWd
Based on this:
noexcept specifier (since C++11) - cppreference.com
The noexcept-specification is not a part of the function type (just like dynamic exception specification) and can only appear as a part of a lambda declarator or a top-level function declarator when declaring functions, variables, non-static data members of type function, pointer to function, reference to function, or pointer to member function, and also when declaring a parameter or a return type in one of those declarations that in turn happens to be a pointer or reference to function. It cannot appear in a typedef or type alias declaration.
void f() noexcept; // the function f() does not throw void (*fp)() noexcept(false); // fp points to a function that may throw void g(void pfa() noexcept); // g takes a pointer to function that doesn't throw // typedef int (*pf)() noexcept; // error(until C++17)
The noexcept-specification is a part of the function type and may appear as part of any function declarator. (since C++17)
So in C++17 when noexcept is part of function type, then template specialization should take it into account. So looks like gcc 13 is right and other compilers are wrong.
I've also found something like this: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4533.html
On other hand there is code compatibility issues, so I would not be surprised this could be controlled by some compilation flag (and different default behavior was selected). I would recommend review compiler documentation about this.
Disclaimer I'm not language lawyer so maybe someone can provide better information.
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