2016-09-25 69 views
0

我有一个函数,我想调用另一个函数并打印它的名字并处理它的结果。它工作正常为什么将函数作为&名称和名称传递给不同的指针?

#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) { 
    IS_API_CALL(&api_call_bar); 
    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) { 
    func(args...); 
    auto name = getFuncNameByPtr(func); // <-- HERE. &func doesnt work 
    std::cout << name << " was called\n"; 
} 

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

这一个打印api_call_bar was called这很好。对我而言,有趣的部分是标记为<-- HERE的部分。如果我通过它作为&func它不能正常工作了(名称不是由地图中的指针找到)。为什么这样?我认为它应该完全一样。

+1

_“我认为它应该完全一样。”_为什么?为什么你将函数指针转换为void *'并返回?我不记得是否允许这样做,这本身就是一个足够的理由不这样做。 –

+0

@LightnessRacesinOrbit,因为&func和func应该评估为相同的指针?没有? –

+1

有趣的是你怎么不使用地图功能... –

回答

3

你被隐式转换为函数参数声明的指针。由于你实际上不能将一个函数作为参数传递给函数,因此编译器(默默地 - 恕我直言,至少应该是一个警告)将函数类型转换为指针类型。所以,当你声明:

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

这是真的,如果你宣布

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

这意味着当您使用api_exec&func,你得到的指针参数(所以指针指针),而不是参数的值。

同样的事情发生在数组中,这也混淆了没有意识到它的人。

+0

也许值得注意的是:将'func'定义为函数的引用('int(&func)(Args ...)')可以避免整个问题。 – hvd

+0

它会*更有意义的语言将函数类型参数作为参考而不是指针,但C++试图与C没有引用兼容... –

相关问题