The function is of type void() , and if you take the address of it, you get a pointer to this function void(*)() . They are not the same type, although a function can decay to a pointer to a function in the same way that arrays decay to pointers to the first member.
This means that you can declare a function:
void f();
and assign it to a function pointer (of the same signature):
void (*p_to_f)() = f;
and the function decays into a pointer to a function.
That's why I think it may be difficult to understand the difference between void() and void(*)() , but they are different types, and this difference can be important in templates (where this decay does not necessarily occur).
One important example of when decay does not occur is the matching of specialized patterns. Consider what std::function does, for example:
template <class> class function; template <class R, class ... Args> class function<R(Args...)> { };
The fact that specialization refers to the type of function is different from whether it was specialized in the type of function pointer.
function<void(int,int)> f;//matches specialisation function<void(*)(int,int)> g;//does not match specialisation
In response to an OP comment (now deleted):
To also combine pointers to functions that you can perform:
template <class R, class ... Args> function<R(*)(Args...)> : function<R(Args...>{};
which essentially means that you are considering functions and function pointers are the same. If you want to combine as many functions as you can, you also need to consider member functions, member functions, and noexcept functions (as in C ++ 17). If you want to be completely thorough, there are also & , && , const & , const&& , volatile etc., but I wouldn’t worry about them if they really didn’t come.