次のtypedefについて考えてみます。
typedef int (*f1)(float);
typedef f1 (*f2)(double);
typedef f2 (*f3)(int);
f2
は、関数ポインターを返す関数です。 f3
と同じですが、関数のタイプ、f3
が返すポインタはf2
です。 typedefなしでf3
を定義するにはどうすればよいですか? typedefはf3
を定義するためのより簡潔で理解しやすい方法であることを知っています。ただし、ここでの私の意図は、C構文をよりよく理解することです。
f1
の宣言から始めます。
int (*f1)(float);
f2
をf1
を返す関数へのポインタにしたいので、上記の宣言のf1
をf2
の宣言に置き換えます。
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
C++では、テンプレートの奇跡により、これが少し簡単になります。
#include <type_traits>
std::add_pointer<
std::add_pointer<
std::add_pointer<
int(float)
>::type(double)
>::type(int)
>::type wow;
Typedefと同じですが、名前の代わりに関数定義を配置するだけです。
f2
は次のようになります。
typedef int (*(*f2)(double))(float);
できるよ f3
これは宿題だと思っているので、練習問題として;)
しないでください。できますが、非常に混乱します。 Typedefは、この短いコードの作成と読み取りを容易にするためにあります。
引数を取らず、関数ポインターint (*)(float)
を返す関数f
は、おそらく(unested)のようになります。
int (*f())(float);
その後は、LISPのようになるまで括弧を追加し続ける必要があります。
右から左への規則 を学ぶ:
「右から左」の規則は、C宣言を解読するための完全に規則的な規則です。また、それらの作成にも役立ちます。
使用する 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;