print
is a function, but it is implicitly convertible to a function pointer type. Quoted from cppref:
Function to pointer
An lvalue of function type T can be implicitly
converted to a prvalue pointer to that function. This does not apply
to non-static member functions because lvalues that refer to
non-static member functions do not exist.
So, in your case:
int (*p)(int) = print; // Conversion happens.
int (*q)(int) = &print; // Conversion does not happen.
Implicit conversion kicks in automatically when it is needed to make the program compile, and is not applied otherwise.
With respect to function calling, it is about the built-in function call operator ()
. According to cppref, the built-in function call operator is applicable to both an lvalue expression that refers to a function and a pointer to function. In your case:
p(8); // The function call operator is applied to a pointer to function.
(*p)(8); // The function call operator is applied to an lvalue reference to function.
For your reference (emphasis mine):
Built-in function call operator
A function call expression, such as E(A1, A2, A3), consists of an
expression that names the function, E, followed by a possibly empty
list of expressions A1, A2, A3, ..., in parentheses. The expression
that names the function can be
a) lvalue expression that refers to a function
b) pointer to function
...