web-dev-qa-db-ja.com

関数ポインタを返す関数のC構文

次のtypedefについて考えてみます。

typedef int (*f1)(float);
typedef f1 (*f2)(double);
typedef f2 (*f3)(int);

f2は、関数ポインターを返す関数です。 f3と同じですが、関数のタイプ、f3が返すポインタはf2です。 typedefなしでf3を定義するにはどうすればよいですか? typedefはf3を定義するためのより簡潔で理解しやすい方法であることを知っています。ただし、ここでの私の意図は、C構文をよりよく理解することです。

35
keveman

f1の宣言から始めます。

int (*f1)(float);

f2f1を返す関数へのポインタにしたいので、上記の宣言のf1f2の宣言に置き換えます。

int (*      f1     )(float);
            |
      +-----+-----+
      |           |
      v           v
int (*(*f2)(double))(float);

宣言は次のようになります

        f2                   -- f2
       *f2                   -- is a pointer
      (*f2)(      )          -- to a function
      (*f2)(double)          --   taking a double parameter
     *(*f2)(double)          --   returning a pointer
    (*(*f2)(double))(     )  --   to a function
    (*(*f2)(double))(float)  --     taking a float parameter
int (*(*f2)(double))(float)  --     returning int

f3についても同じ手順を繰り返します。

int (*(*    f2    )(double))(float);
            |
        +---+----+
        |        |
        v        v
int (*(*(*f3)(int))(double))(float);

と読む

          f3                           -- f3
         *f3                           -- is a pointer
        (*f3)(   )                     -- to a function
        (*f3)(int)                     --   taking an int parameter
       *(*f3)(int)                     --   returning a pointer
      (*(*f3)(int))(      )            --   to a function
      (*(*f3)(int))(double)            --     taking a double parameter
     *(*(*f3)(int))(double)            --     returning a pointer
    (*(*(*f3)(int))(double))(     )    --     to a function
    (*(*(*f3)(int))(double))(float)    --       taking a float parameter
int (*(*(*f3)(int))(double))(float);   --       returning int
124
John Bode

C++では、テンプレートの奇跡により、これが少し簡単になります。

#include <type_traits>

std::add_pointer<
    std::add_pointer<
        std::add_pointer<
            int(float)
        >::type(double)
    >::type(int)
>::type wow;
14
Puppy

Typedefと同じですが、名前の代わりに関数定義を配置するだけです。

f2は次のようになります。

typedef int (*(*f2)(double))(float);

できるよ f3これは宿題だと思っているので、練習問題として;)

7
Blindy

しないでください。できますが、非常に混乱します。 Typedefは、この短いコードの作成と読み取りを容易にするためにあります。

引数を取らず、関数ポインターint (*)(float)を返す関数fは、おそらく(unested)のようになります。

int (*f())(float);

その後は、LISPのようになるまで括弧を追加し続ける必要があります。

右から左への規則 を学ぶ:

「右から左」の規則は、C宣言を解読するための完全に規則的な規則です。また、それらの作成にも役立ちます。

4

使用する std::function

typedef std::function<int(float)> f1;
typedef std::function<f1(double)> f2;
typedef std::function<f2(int)>    f3;

または

typedef std::function<std::function<std::function<int(float)>(double)>(int)> f3;
0
Inverse