"Functions" versus "function pointers" -- what's the difference?
d, function, function-pointers
Solution
Short Answer:
- `is(T == function)` Whether `T` is a function
- `isFunctionPointer!T` Whether `T` is a function pointer (and not a delegate)
- `isDelegate!T` Whether `T` is a delegate
- `isSomeFunction!T` Whether `T` is a function, a function pointer, or a delegate
Long Answer:
A function is, well, a function.
auto func(int val) {...}
It's a chunk of code with a name that you can call using that name. You give it arguments, it does whatever it does, and it returns a result. You can call it, but you can't pass it around. You need a function pointer for that.
A function pointer is a pointer to a function. So just like `int` is an `int` and `int*` is a pointer to an `int`, and `int` is not a pointer to `int`, a function isn't a function pointer. If you want a function pointer, you need a pointer to a function. The syntax is different from how it is with `int`, but it's the same concept.
A delegate is a function pointer with state. So for instance, in
int foo(int value)
{
int bar()
{
return value + 5;
}
auto barDel = &bar;
return barDel();
}
void main()
{
auto fooFunc = &foo;
}
`foo` is a function, `bar` is a nested function which has access to its outer scope, and `barDel` is a delegate, because it's a function pointer with state (the outer state that `bar` has access to). If you pass `barDel` to another function (or return it), you'll get a closure (unless the function it's passed to takes the delegate by `scope`, in which case that function guarantees that the delegate will not escape its scope), because that state needs to be put on the heap so that it continues to exist even if the function call that its state comes from has completed when it's called. `funcFoo`, on the other hand, is a function pointer, because `foo` doesn't have any outer state. If `bar` were `static`, then `barDel` would also be a function pointer rather than a delegate, because `bar` would no longer have access to the function that it's in (though its body would then have to be changed, since it would no longer have access to `value`).
Now, as to your example. `Object.toString` is a member function of `Object`. So, it's a function. It has no state associated with it. Functions never do. Its current signature is
string toString();
But because it's a member function of `Object`, its signature is really something like
string toString(Object this);
`this` is passed to `toString` as an argument. It's not state associated with `toString`. So, `&Object.toString` is not a delegate. It's just a function pointer. And `Object.toString` isn't a function pointer, so even if `&Object.toString` were a delegate, `static assert(isDelegate!(typeof(Object.toString)))` would still fail, because in order to be a delegate, it must be a function pointer, which it's not. It's a function.
Now, unfortunately, `typeof(&Object.toString)` is considered to be `string function()` rather than `string function(Object)`, so using it to call `toString` with an actual `Object` takes a bit of work. It can be done, but I don't remember how at the moment (and it's a bit ugly IIRC). But it wouldn't be a delegate regardless, because there's no state associated with it.
If you want a function that you can pass an `Object` to and have it call a member function, then you could do something like
auto obj = getObjectFromSomewhere();
auto func = function(Object obj){return obj.toString();};
auto result = func(obj);
If you want to associate an object with a member function and be able to call that member function on that object without having to pass the object around, then you just wrap it in a delegate:
auto obj = getObjectFromSomewhere();
auto del = delegate(){return obj.toString();};
auto result = del();
This bit of code should sum things up and illustrate things fairly well:
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` is `true` for all of them, because they're all either functions, function pointers without state, or delegates.
`foo`, `bar`, `boz`, and `Object.toString` are all functions, so they're `true` for `is(T == function)` but not for the others.
`fooFunc`, `bozFunc`, and `&Object.toString` are function pointers without state, so they're `true` for `isFunctionPointer!T` but not for the others.
`barDel` is a delegate, so it's `true` for `isDelegate!T` but not for the others.
Hopefully, that clears things up for you.
Problem
I'm really confused at the documentation of `isSomeFunction`, as well as at the following code: ``` static assert(!isFunctionPointer!(typeof(Object.toString))); // makes sense static assert(!isDelegate!(typeof(Object.toString))); // what?? static assert( isSomeFunction!(typeof(Object.toString))); // what?? ``` Could someone please explain the difference between a "function" and a "function pointer" to me?