2016-09-25 6 views
0

私は別の関数を呼び出してその名前を出力し、その結果を扱いたいという関数を持っています。それは正常に動作します&nameとnameとして関数を渡すのがなぜ異なるポインタですか?

#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); 
} 

この1つは、api_call_bar was calledを正常に印刷します。私にとって興味深い部分は、<-- HEREというマークが付けられています。 &funcとして渡すと正しく動作しません(名前はマップ内のポインタによって見つかりません)。それはなぜそうですか?私はそれがまったく同じであるべきだと思います。

+1

_ "私はそれがまったく同じであるべきだと思います。" - それはなぜですか?なぜ関数ポインタを 'void *'に変換して戻ってきたのですか?私はそれが許されているかどうか覚えていません。それ自体はそれをしない十分な理由です。 &funcとfuncは同じポインタを評価する必要があるため、 –

+0

@ LightnessRacesinOrbit?いいえ? –

+1

あなたはマップの機能を使用していません... –

答えて

3

関数の引数宣言のポインタへの暗黙的な変換が行われています。実際に関数を引数として関数に渡すことはできないので、コンパイラ(少なくともIMHOは警告でなければなりません)は、関数型をポインタ型に変換します。あなたが宣言するときに:

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

をあなたは

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

を宣言したかのように、それはあなたがapi_exec&funcを使用する場合、あなたはその引数(へのポインタへのポインタを取得していることを意味している本当にですポインタ)であり、引数の値ではありません。

アレイでも同じことが起こります。これは、それを認識していない人も混乱します。

+0

関数( 'int(&func)(Args ...)')への参照として 'func'を定義すると、問題全体が回避されました。 – hvd

+0

*関数型引数をポインターではなく参照として扱う言語にはもっと意味がありますが、C++は参照を持たないCと互換性を持っています... –

関連する問題