C++20 added the rule of addressable function 16.5.4.2.1 [namespace.std]/6: -- emphasis is mine --
Let F denote a standard library function ([global.functions]), a standard library static member function, or an instantiation of a standard library function template. Unless F is designated an addressable function, the behavior of a C++ program is unspecified (possibly ill-formed) if it explicitly or implicitly attempts to form a pointer to F. [ Note: Possible means of forming such pointers include application of the unary & operator ([expr.unary.op]), addressof ([specialized.addressof]), or a function-to-pointer standard conversion ([conv.func]). — end note ] Moreover, the behavior of a C++ program is unspecified (possibly ill-formed) if it attempts to form a reference to F or if it attempts to form a pointer-to-member designating either a standard library non-static member function ([member.functions]) or an instantiation of a standard library member function template.
The math functions as far as I can tell, are not marked by the spec as addressable functions.
Does it mean that the following code is illegal since C++20 (as noted by cppreference with an example of other standard library functions):
// unspecified and illegal?
auto func = static_cast<float (*)(float, float)>(std::pow);
std::cout << func(2, 4) << std::endl;
and what about the following code, is it legal?
// legal? or unspecified and illegal?
std::function<float(float, float)> f = static_cast<float(*)(float, float)>(std::pow);
std::cout << f(2, 3) << std::endl;
- What is the reason for this new restriction in C++20?
- Isn't such a restriction breaking legacy code?
- What is the right way since C++20 to hold or pass around non-addressable-functions?