Aiko
Aiko

Reputation: 193

Does an implicit conversion from function pointer to function exist?

I am primarily making this post to clarify some confusing/misleading information about function pointers that I stumbled upon on Stackoverflow.

Let's begin with an example:

#include <iostream>

void func ()
{
    std::cout<<"func here"<<'\n';
}

int main()
{
    void (*fp)()=func;
    void (&fref)()=func;

    func();//call through function
    (&func)();//call through function pointer
    (*fp)();//call through function
    fp();//call through function pointer
    fref();//call through function
    (&fref)();//call through function pointer
}

This prints:

func here
func here
func here
func here
func here
func here

As can be seen a function can be used in place of a function pointer most of the time thanks to function to function pointer decay cppreference.

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.

But apart from that it looks a function pointer can also be used in place of a function as I can use it to call a function without explicitly derefencing.

Furthermore this Stackoverflow answer

Note also that you do not need to use the unary * to make the call via the function pointer; both (*p1_foo)(); and (p1_foo)(); have the same result, again because of the function-to-function-pointer conversion.

and this Stackoverflow answer

There's a dual convenience as well: a function pointer in call position is automatically converted to a function value, so you don't have to write * to call through a function pointer.

Make it seem like there exists an implicit function pointer to function conversion.

Upvotes: 1

Views: 494

Answers (1)

Aiko
Aiko

Reputation: 193

No

An implicit conversion from function pointer to function doesn't exist.

As of ISO International Standard ISO/IEC 14882:2020(E) – Programming Language C++ there are no mentions of such a conversion.

But apart from that it looks a function pointer can also be used in place of a function as I can use it to call a function without explicitly derefencing.

This is probably why some SO answers (and even some less known C++ books!) come to the incorrect conclusion that a function pointer is essentially the same as a function and use the function to function pointer decay as evidence. However this implicit conversion only works in one way! Meaning that the quoted section of the first SO answer is incorrect.

Why does the function call succeed anyway?

The reason as to why we can call a function using a function pointer without explicit derefernce actually lies in the way the built in function call operator "()" works cppreference:

The expression that names the function can be a) lvalue expression that refers to a function b) pointer to function c) explicit class member access expression that selects a member function d) implicit class member access expression, e.g. member function name used within another member function.

Aha! So the function call operator can directly take a function pointer as expression. There is no implicit conversion. If you read the quote from the second SO answer it explicitly mentions that the function pointer needs to be in call position that is called using the function call operator.

This also means that in all contexts outside of a function call a function pointer does need to be dereferenced where a function is expected such as when initializing a function reference:

void func ()
{
    std::cout<<"func here"<<'\n';
}

int main()
{
    void (*fp)()=func;//OK (implicit function to function pointer decay)

    void (&&fref1)()=&func;//error: invalid initialization of reference of type 'void (&&)()' from expression of type 'void (*)()'

    void (&fref2)()=*fp;//OK

    void (&fref3)()=fp;// error: invalid initialization of reference of type 'void (&)()' from expression of type 'void (*)()'
}

Upvotes: 5

Related Questions