4

我对的文档isSomeFunction以及以下代码感到非常困惑:

static assert(!isFunctionPointer!(typeof(Object.toString)));  // makes sense
static assert(!isDelegate!(typeof(Object.toString)));         // what??
static assert( isSomeFunction!(typeof(Object.toString)));     // what??

有人可以向我解释“函数”和“函数指针”之间的区别吗?

4

1 回答 1

6

简短的回答:

  • is(T == function)      是否T是函数
  • isFunctionPointer!T  是否T是函数指针(而不是委托)
  • isDelegate!T                是否T为代表
  • isSomeFunction!TT是函数、函数指针        还是委托

长答案:

函数就是函数。

auto func(int val) {...}

它是一段代码,您可以使用该名称调用该名称。你给它参数,它做任何事情,它返回一个结果。你可以调用它,但你不能传递它。你需要一个函数指针。

函数指针是指向函数的指针。因此,就像intis anintint*是指向 an 的指针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它没有任何外部状态。如果barstatic,那么barDel也将是一个函数指针而不是一个委托,因为bar将不再有权访问它所在的函数(尽管它的主体必须更改,因为它不再有权访问value)。

现在,至于你的例子。Object.toString是 的成员函数Object。所以,它是一个函数。它没有与之关联的状态。函数永远不会。它当前的签名是

string toString();

但是因为它是 的成员函数Object,所以它的签名实际上类似于

string toString(Object this);

thistoString作为参数传递给。它不是与 关联的状态toString。所以,&Object.toString不是代表。它只是一个函数指针。并且Object.toString不是函数指针,所以即使&Object.toString 委托,static assert(isDelegate!(typeof(Object.toString)))仍然会失败,因为要成为委托,它必须是函数指针,但事实并非如此。这是一个功能。

现在,不幸的是,typeof(&Object.toString)被认为是string function()而不是string function(Object),因此使用它来调用toString实际Object需要一些工作。可以做到,但我现在不记得是怎么做到的(而且 IIRC 有点难看)。但无论如何它都不会是委托,因为没有与之关联的状态。

如果您想要一个可以传递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的函数指针,所以它们是用于但不是用于其他的。trueisFunctionPointer!T

barDel是一个代表,所以它是true给其他人的,isDelegate!T但不是给其他人的。

希望这可以为您解决问题。

于 2012-06-17T02:18:23.547 回答