lukas.pukenis lukas.pukenis - 1 year ago 58
C++ Question

Why passing function as &name and name gives different pointers?

I have a function which I want to call another function and print its name and handle its results. It works fine

#include <iostream>
#include <string>
#include <map>

std::map<void *, std::string> ptr_map;
#define IS_API_CALL(fun) ptr_map[fun] = __FUNCTION__;

int api_call_bar(double x) {
return 0;

std::string getFuncNameByPtr(void * addr) {
for (auto it = ptr_map.begin(); it != ptr_map.end(); ++it) {
if (it->first == addr) return it->second;

return "???";

template <typename... Args>
void api_exec(int func(Args...), Args... args) {
auto name = getFuncNameByPtr(func); // <-- HERE. &func doesnt work
std::cout << name << " was called\n";

int main() {
api_exec(&api_call_bar, 2.0);

This one prints
api_call_bar was called
which is fine. The interesting part for me is part marked
<-- HERE
. If I pass it as
it doesn't work properly anymore(name is not found by pointer in a map). Why is it so? I think it should be exactly the same.

Answer Source

You're getting hit by the implicit conversion to pointer for function args. Since you can't actually pass a function as an argument to a function, the compiler (silently -- IMHO should at least be a warning) converts the function type to a pointer type. So when you declare:

void api_exec(int func(Args...), Args... args)

it's really as if you declared

void api_exec(int (*func)(Args...), Args... args)

which means that when you use &func in api_exec, you're getting a pointer to the argument (so a pointer to a pointer), not the value of the argument.

The same thing happens with arrays, which also confuses people who don't realize it.