-
-
Notifications
You must be signed in to change notification settings - Fork 705
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
isCallable fails for template opCall overload #9780
Labels
Comments
simen.kjaras commented on 2019-09-27T06:34:43ZIt's impossible to distinguish between the above case and this:
struct S { enum opCall(T) = true; }
Clearly, the latter is *not* callable.
To illustrate the situation perhaps more clearly:
struct S {
template opCall(T) {
static if (is(T == int)) {
void opCall(T t) {}
} else {
enum opCall = 14;
}
}
}
The above is perfectly valid code, but should isCallable!S return true? |
snarwin+bugzilla commented on 2019-09-27T15:35:26ZSeems like this is an issue with the interface, then, not the implementation; the question "is S.init callable" is undecidable, so there's not much use trying to pretend we can answer it.
One possible solution would be a trait like `isCallableWith!(S.init, int)`, that requires the user to specify the argument type(s). That way, we could just check with __traits(compiles) whether the call is valid or not. |
maxsamukha commented on 2019-09-28T06:27:27Z(In reply to Paul Backus from comment #2)
> One possible solution would be a trait like `isCallableWith!(S.init, int)`,
> that requires the user to specify the argument type(s). That way, we could
> just check with __traits(compiles) whether the call is valid or not.
That does not take into account rvalue-ness of the arguments:
void foo(ref int) {}
store
static if (isCallableWith!(typeof(1)))
foo(1); // error
isCallableWith would have to accept the actual arguments, (type, rvalue-ness) pairs, or both.
And if one implements isCallableWith for functions, he should also implement isInstantiatableWith for templates. And that is a case for general __traits(matchFunction/matchTemplate, symbol, args) that would return the overloads callable/instantiatable with args. isCallableWith/isInstantiatableWith could be built on that. |
maxsamukha commented on 2019-09-28T06:29:30Z(In reply to Max Samukha from comment #3)
> isCallableWith!(typeof(1))
Typo: isCallableWith!(foo, typeof(1)) |
snarwin+bugzilla commented on 2019-09-28T15:30:04Z(In reply to Max Samukha from comment #3)
> That does not take into account rvalue-ness of the arguments:
>
> void foo(ref int) {}
> store
> static if (isCallableWith!(typeof(1)))
> foo(1); // error
>
> isCallableWith would have to accept the actual arguments, (type,
> rvalue-ness) pairs, or both.
Then perhaps the best solution is to add a note to the documentation of isCallable highlighting its shortcomings, and encourage everyone to instead use __traits(compiles) directly with the actual function call they want to make. |
simen.kjaras commented on 2020-08-10T07:26:58Z*** Issue 21137 has been marked as a duplicate of this issue. *** |
simen.kjaras commented on 2020-08-10T07:40:37ZIt's impossible to solve this in the general case, and even the special cases can't be solved in library code, but a __traits could check if the only member of the template is a callable (potentially also if all possible members would be callables). |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
snarwin+bugzilla (@pbackus) reported this on 2019-09-26T18:50:31Z
Transfered from https://issues.dlang.org/show_bug.cgi?id=20246
CC List
Description
import std.traits: isCallable; struct S { int opCall(T)(T) { return 0; } } static assert(isCallable!(S.init)); --- The above static assert should pass, but instead fails.The text was updated successfully, but these errors were encountered: