簡潔な答え:
is(T == function)
T
関数 かどうか
isFunctionPointer!T
T
関数ポインター (デリゲートではない) かどうか
isDelegate!T
T
デリゲート かどうか
isSomeFunction!T
T
関数、関数ポインター、またはデリゲートのいずれである か
長い答え:
関数は、まあ、関数です。
auto func(int val) {...}
これは、その名前を使用して呼び出すことができる名前を持つコードのチャンクです。引数を与えると、何でも実行し、結果を返します。呼び出すことはできますが、渡すことはできません。そのためには関数ポインタが必要です。
関数ポインタは、関数へのポインタです。したがってint
、int
とint*
が へのポインタであり、 が へのポインタint
でint
はないint
のと同様に、関数は関数ポインタではありません。関数ポインタが必要な場合は、関数へのポインタが必要です。とは構文が異なりますがint
、考え方は同じです。
デリゲートは、状態を持つ関数ポインターです。たとえば、
int foo(int value)
{
int bar()
{
return value + 5;
}
auto barDel = &bar;
return barDel();
}
void main()
{
auto fooFunc = &foo;
}
foo
関数でbar
あり、外側のスコープにアクセスできるネストされた関数であり、デリゲートです。これは、状態 (アクセスできるbarDel
外側の状態) を持つ関数ポインターであるためです。bar
別の関数に渡すbarDel
(または返す) と、クロージャーが得られます (渡された関数がデリゲートを受け取る場合を除きます。scope
この場合、その関数はデリゲートがそのスコープをエスケープしないことを保証します)。呼び出されたときに状態が由来する関数呼び出しが完了した場合でも存在し続けるように、ヒープに置かれます。funcFoo
一方、foo
外部状態がないため、関数ポインターです。bar
だったらstatic
、barDel
また、デリゲートではなく関数ポインターになります。bar
これは、それが含まれる関数にアクセスできなくなるためです (ただし、 にアクセスできなくなるため、本体を変更する必要がありますvalue
)。
さて、あなたの例について。Object.toString
のメンバー関数ですObject
。というわけで関数です。それに関連付けられた状態はありません。関数は決してしません。その現在の署名は
string toString();
しかし、これは のメンバー関数であるためObject
、そのシグネチャは実際には次のようになります。
string toString(Object this);
this
引数として渡されtoString
ます。に関連付けられた状態ではありませんtoString
。だから、&Object.toString
デリゲートではありません。単なる関数ポインタです。AndObject.toString
は関数ポインターではないため、デリゲートで&Object.toString
あっstatic assert(isDelegate!(typeof(Object.toString)))
たとしても失敗します。デリゲートになるには、関数ポインターである必要がありますが、そうではありません。関数です。
残念ながら、はではなくtypeof(&Object.toString)
と見なされるため、実際の呼び出しに使用するには少し手間がかかります。実行できますが、現時点ではその方法を覚えていません (そして、IIRC は少し醜いです)。ただし、状態が関連付けられていないため、デリゲートにはなりません。string function()
string function(Object)
toString
Object
を渡しObject
てメンバー関数を呼び出すことができる関数が必要な場合は、次のようにすることができます
auto obj = getObjectFromSomewhere();
auto func = function(Object obj){return obj.toString();};
auto result = func(obj);
オブジェクトをメンバー関数に関連付け、オブジェクトを渡すことなくそのオブジェクトでそのメンバー関数を呼び出せるようにする場合は、デリゲートでラップするだけです。
auto obj = getObjectFromSomewhere();
auto del = delegate(){return obj.toString();};
auto result = del();
このコードは物事を要約し、物事をかなりよく示しているはずです:
int foo(int value)
{
int bar()
{
return value + 5;
}
static assert( is(typeof(bar) == function));
static assert(!isFunctionPointer!(typeof(bar)));
static assert(!isDelegate!(typeof(bar)));
static assert( isSomeFunction!(typeof(bar)));
auto barDel = &bar;
static assert(!is(typeof(barDel) == function));
static assert(!isFunctionPointer!(typeof(barDel)));
static assert( isDelegate!(typeof(barDel)));
static assert( isSomeFunction!(typeof(barDel)));
static int boz(int i)
{
return i + 2;
}
static assert( is(typeof(boz) == function));
static assert(!isFunctionPointer!(typeof(boz)));
static assert(!isDelegate!(typeof(boz)));
static assert(isSomeFunction!(typeof(boz)));
auto bozFunc = &boz;
static assert(!is(typeof(bozFunc) == function));
static assert( isFunctionPointer!(typeof(bozFunc)));
static assert(!isDelegate!(typeof(bozFunc)));
static assert( isSomeFunction!(typeof(bozFunc)));
return boz(bar());
}
static assert( is(typeof(foo) == function));
static assert(!isFunctionPointer!(typeof(foo)));
static assert(!isDelegate!(typeof(foo)));
static assert( isSomeFunction!(typeof(foo)));
void main()
{
auto fooFunc = &foo;
static assert(!is(typeof(fooFunc) == function));
static assert( isFunctionPointer!(typeof(fooFunc)));
static assert(!isDelegate!(typeof(fooFunc)));
static assert( isSomeFunction!(typeof(fooFunc)));
}
static assert( is(typeof(Object.toString) == function));
static assert(!isFunctionPointer!(typeof(Object.toString)));
static assert(!isDelegate!(typeof(Object.toString)));
static assert( isSomeFunction!(typeof(Object.toString)));
static assert(!is(typeof(&Object.toString) == function));
static assert( isFunctionPointer!(typeof(&Object.toString)));
static assert(!isDelegate!(typeof(&Object.toString)));
static assert( isSomeFunction!(typeof(&Object.toString)));
isSomeFunction
それらはすべて、関数、状態のない関数ポインター、またはデリゲートtrue
のいずれかであるためです。
foo
、bar
、boz
、およびObject.toString
はすべて関数であるため、それらは他のものtrue
でis(T == function)
はありません。
fooFunc
、bozFunc
、およびはstate のない&Object.toString
関数ポインターであるため、それらは他のものではありません。true
isFunctionPointer!T
barDel
デリゲートなので、他の人のtrue
ためisDelegate!T
ではありません。
うまくいけば、それで問題が解決します。