7

I have a function that accepts as an argument a function pointer. Surprisingly, I can pass in both a function pointer and an ordinary function:

#include <iostream>
#include <functional>

int triple(int a) {
    return 3*a;
}

int apply(int (*f)(int), int n) {
    return f(n);
}

int main() {
    std::cout << apply(triple, 7) << "\n";
    std::cout << apply(&triple, 7) << "\n";
}

I'm confused about why this works. Is there an implicit conversion from functions to function pointers?

5
  • 1
    And, because of the way the address and dereferencing rules work for functions, you could also use &&f, &&&f, etc., with as many &’s as you like. Similarly, in apply, you could write (*f)(n), (**f)(n), etc. Commented Jan 25, 2019 at 3:24
  • @PeteBecker Where can I learn more about this? Does this work for C as well? Commented May 8, 2023 at 15:30
  • @LoverofStructure -- first, && won't work; it's the logical and operator. That should have been & &f, & & &f, etc. This is just a quirk of the grammar. It's not actually useful. Yes, it's the same in C. Commented May 8, 2023 at 15:53
  • @PeteBecker 1. I can't get the OP's code above to work with & &triple, but it does work with return (******f)(n);. 2. Where in the C and C++ standards documents can I learn about such behavior? (I assume that there are certain environments in which f "decays" to *f or &f.) Commented May 8, 2023 at 16:18
  • @PeteBecker I found it (for C) in the discussion of function designators. However, did you mean &f, &*&f, &*&*&f instead? I can't figure out a way to use indefinitely repeated ampersands. Commented May 9, 2023 at 1:20

1 Answer 1

9

Yes, there's function-to-pointer implicit conversion:

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.

And

A pointer to function can be initialized with an address of a non-member function or a static member function. Because of the function-to-pointer implicit conversion, the address-of operator is optional:

void f(int);
void (*p1)(int) = &f;
void (*p2)(int) = f; // same as &f

That means when being used in context requiring a function pointer, function (except for non-static member function) would convert to function pointer implicitly, and the usage of operator& is optional.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.