キャストで理解できない場所　関数ポインタ


c++中級編の参考書の下記のプログラムコメントになっている部分の挙動がわからないです。

[code]

    reinterpret_cast<int(*)(const void *, const void*)>(int_cmp)
    
[/code]

キャストしているのはかわかるのですが`int(*)`というのと`(const void*,const void*)`  
が何をしているのかがわからないです、ポインタがどうたらっていうキャストをしているのはなんとなく察しがつくのですがしっかり理解したいので解説お願いします。

[code]

    int int_cmp(const int* a,const int* b){
        if (*a < *b) {
            return -1;
        }
        else if(*a > *b) {
            return 1;
        }else {
            return 0;
        }
    }
    
    int main() {
    
        int i = 0;
        int nx = 0;
        int no = 0;
        cout << "配列の要素数:";
        cin >> nx;
    
        int *x = new int[nx];
        cout << nx << "個の要素数を昇順に入力せよ、\n";
    
        for (i = 0; i < nx; i++) {
            cout << "x[" << i << "]:";
            cin >> x[i];        
        }
    
        cout << "探索する値:";
        cin >> no;
    
        int *p = reinterpret_cast<int*>(
            bsearch(&no, x, nx, sizeof(int),
            /*ここです。*/
            reinterpret_cast<int(*)(const void *, const void*)>(int_cmp))
        );
            /* */
    
        if (p != NULL) {
            cout << "x[" << (p - x) << "]が一致します。\n";
        }
        else {
            cout << "見つかりません\n";
        }
    
        _getch();
        return 0;
    }
    
[/code]




**`int(*)(const void *, const void*)`について**

`int(*)`と`(const void *, const
void*)`と分けてしまうと、わかりにくくなってしまうので、まとめて考えます。まず`(*)`は後で考えることにして、`F`と置き換えてみます。すると元の式は

`int F(const void *, const void*)`

になります。こうしてみると、この式は全体として関数の宣言の形になっており、実際、 **`const void
*`の引数を二つ取り、`int`を返す関数**を意味しています。ここで`F`は`(*)`であり、このアスタリスクはポインタを示していることを併せて考えれば、全体として`int(*)(const
void *, const void*)`は、

**`const void *`の引数を二つ取り、`int`を返す関数へのポインタ**

ということになります。

* * *

**キャストについて**

関数 bsearch の宣言がないので、cstdlib で宣言されている標準関数の bsearch だと仮定して説明します。

bsearch の最後の引数の型は`int (*)(const void*,const void*)`ですが、その一方、渡したい関数 int_cmp
の型は`int int_cmp(const int* a,const int*
b)`です。関数の型は、戻り値の型と引数の型を合わせたものなので、引数の型が合わず、直接、関数のポインタを渡そうとしてもコンパイルエラーになってしまいます。それでキャストが必要になります。

`reinterpret_cast<int(*)(const void *, const void*)>(int_cmp)`

の意味は、 **`const int *`の引数を二つ取り、`int`を返す関数へのポインタ`int_cmp` を`const void
*`の引数を二つ取り、`int`を返す関数へのポインタ**に変換せよ、ということです。関数から関数へのキャストは、C++の仕様で決まったルールはないので、`reinterpret_cast`で強引に変換する必要があります。




**`int(*)(const void *, const void*)`について**

`int(*)`と`(const void *, const
void*)`と分けてしまうと、わかりにくくなってしまうので、まとめて考えます。まず`(*)`は後で考えることにして、`F`と置き換えてみます。すると元の式は

`int F(const void *, const void*)`

になります。こうしてみると、この式は全体として関数の宣言の形になっており、実際、 **`const void
*`の引数を二つ取り、`int`を返す関数**を意味しています。ここで`F`は`(*)`であり、このアスタリスクはポインタを示していることを併せて考えれば、全体として`int(*)(const
void *, const void*)`は、

**`const void *`の引数を二つ取り、`int`を返す関数へのポインタ**

ということになります。

* * *

**キャストについて**

関数 bsearch の宣言がないので、cstdlib で宣言されている標準関数の bsearch だと仮定して説明します。

bsearch の最後の引数の型は`int (*)(const void*,const void*)`ですが、その一方、渡したい関数 int_cmp
の型は`int int_cmp(const int* a,const int*
b)`です。関数の型は、戻り値の型と引数の型を合わせたものなので、引数の型が合わず、直接、関数のポインタを渡そうとしてもコンパイルエラーになってしまいます。それでキャストが必要になります。

`reinterpret_cast<int(*)(const void *, const void*)>(int_cmp)`

の意味は、 **`const int *`の引数を二つ取り、`int`を返す関数へのポインタ`int_cmp` を`const void
*`の引数を二つ取り、`int`を返す関数へのポインタ**に変換せよ、ということです。関数から関数へのキャストは、C++の仕様で決まったルールはないので、`reinterpret_cast`で強引に変換する必要があります。

