Consider TDPL example om page 150:
auto f = (int i) {};
assert(is(f == function));
That example has a typo, should be:
auto f = (int i) {};
assert(is(typeof(f) == function));
That still doesn't work, which brings us to this bug. The type of the function is deduced as
void function(int i) pure nothrow @safe
and that fails the "is" test when compared against the bare "function" keyword. As "function" by itself does not represent a type, the test should pass for all functions, however qualified.
Comment #1 by maxim — 2013-09-11T13:22:37Z
f is not a function but a function pointer, so the issue is against current design and description of the issue is also misleading by the way.
By the way, this is a good opportunity to raise the question about what 'is' expression should return. There are currently two kinds 'function' and 'delegate' for three cases - a function, function pointer and delegate. Currently 'function' maps to function, not to a pointer and 'delegate' maps to delegate which is inconsistent (there is also inconsistency with not mapping 'function' to function pointer as this keyword is related to function pointers in other use cases).
If 'function' should map to both pointer and a function, then there should be some means to distingiush between them. Another option is to map 'function' to pointer and function should map to returned type .
Comment #2 by ismailsiege — 2017-06-23T00:11:06Z
void testf(){}
void main()
{
static assert(!is(testf == function)); // OK
static assert(is(typeof(testf) == function)); // OK
static assert(is(typeof( (){} ) == delegate)); // fails
}
But "is" doesn't work with function literals themselves in the first place, it is intended to check whether type is equivalent to function pointer or not.
Same goes for:
static if (is(typeof((int, float){}) P == function))
pragma(msg, P);
else
static assert(0); // fails
Comment #3 by ismailsiege — 2017-06-23T00:16:45Z
static assert(is(typeof( (){} ) == function)); // fails as well
This issue doesn't allow to get lambda parameter types tuple, and this blocks my development. I'll try to have a look at the dmd source.
Comment #4 by ismailsiege — 2017-06-23T10:20:17Z
Ok, I'll agree with Maxim, it's probably as it should be.
template isFunctionPointerType(T: FT*, FT)
{
enum isFunctionPointerType = is(FT == function);
}
unittest
{
auto p = (){};
static assert(isFunctionPointerType!(typeof(p)));
}
Comment #5 by petar.p.kirov — 2017-06-23T14:14:04Z
(In reply to Alexander from comment #3)
> static assert(is(typeof( (){} ) == function)); // fails as well
>
> This issue doesn't allow to get lambda parameter types tuple, and this
> blocks my development. I'll try to have a look at the dmd source.
Is the blocking issue that in code similar to the following, there's an error on line 11:
---
import std.traits;
pragma (msg, ReturnType!( (){} )); // void
pragma (msg, Parameters!( (){} )); // ()
pragma (msg, ReturnType!( (int x, double y) => "test" )); // string
pragma (msg, Parameters!( (int x, double y) => "test" )); // (int, double)
void lambdaTypeWithParameter(alias lambda, Param)(Param p)
{
pragma (msg, Parameters!(lambda)); // line 11 - doesn't compile
alias RT = typeof(lambda(p));
pragma (msg, RT); // line 15
}
void main()
{
lambdaTypeWithParameter!(x => "test2")(true); // line 15 -> string
lambdaTypeWithParameter!(x => x)(2); // line 15 -> int
lambdaTypeWithParameter!(x => 3.0 * x)(2); // line 15 -> double
}
---
?
If that's the case, the error is expected since the lambda in that context is polymorphic - an un-instantiated function template meaning that its parameters are not bound to a specific type.
Comment #6 by petar.p.kirov — 2017-06-23T14:15:21Z
Let's keep the bug open until the language authors take an authoritative decision to keep or fix this issue.
Comment #7 by dfj1esp02 — 2017-06-23T16:02:10Z
How it works now:
---
void f(){}
static assert(is(typeof(f)==function));
static assert(is(typeof(&f)==function));
---
line 3: Error: static assert (is(void function() == function)) is false
Looks like function pointer is not recognized as `function` by `is` expression.
Comment #8 by dfj1esp02 — 2017-06-23T16:12:49Z
static assert(is(typeof(&f)==delegate));
fails too, and spec doesn't specify how `is` expression works, which is definitely a bug.
Comment #9 by ismailsiege — 2017-06-23T18:40:23Z
I'm not sure about it being a bug, though I was before. I think spec should be a little more explicit on the difference between function and function pointer types.
For now, this templates solve all my problems:
template isFunctionPointerType(T: FT*, FT)
{
enum isFunctionPointerType = is(FT == function);
}
template ReturnType(FuncType: FT*, FT)
{
static if (is(FT RT == return))
alias ReturnType = RT;
else
static assert(0, "FuncType must be function pointer type");
}
template ParamTypes(FuncType: FT*, FT)
{
static if (is(FT Params == function))
alias ParamTypes = Params;
else
static assert(0, "FuncType must be function pointer type");
}
Comment #10 by robert.schadek — 2024-12-13T18:11:22Z