While writing code involving noexcept
I made a typo and was surprised to see that the program compiled in gcc but not in clang and msvc. Demo
struct C
{
void func() noexcept
{
}
void f() noexcept(noexcept(C::func)) //gcc compiles this but clang and msvc rejects this
{
}
};
So my question is which compiler is right here(if any)?
CodePudding user response:
The program is ill-formed and gcc is wrong in accepting the code because we cannot name a non-static member function in an unevaluated-context like decltype
or sizeof
or noexcept operator
.
This can be seen from expr.prim.id:
An
id-expression
that denotes a non-static data member or `non-static member function of a class can only be used:
- as part of a class member access in which the object expression refers to the member's class or a class derived from that class, or
- to form a pointer to member ([expr.unary.op]), or
- if that id-expression denotes a non-static data member and it appears in an unevaluated operand.
[ Example:
struct S { int m; }; int i = sizeof(S::m); // OK int j = sizeof(S::m 42); // OK
— end example ]
And since the id-expression C::func
denotes the non-static member function but does not fall under any of the three listed categories, the program is ill-formed.
Here is the gcc bug:
GCC compiles invalid use of non static member function in noexcept operator
Note also that if C::func
denoted a non-static data member(instead of member function) then the program would've been well-formed because of the third bullet in the above list. Demo
Similarly, if you were to write &C::func
that would also have worked(well-formed) because of the 2nd bullet in the above quoted list.