get parameters of a function
Alex via Digitalmars-d-learn
digitalmars-d-learn at puremagic.com
Sat Apr 29 01:52:13 PDT 2017
On Saturday, 29 April 2017 at 08:15:06 UTC, Stanislav Blinov
wrote:
> Ah, that calls for something like a isCallableWith template.
> Pay extra care to how you pass parameters in that variadic
> opCall template though. Doing it like in the code above will
> pass everything by value, even though the original S.opCall
> might've expected a reference. To avoid that, auto ref +
> std.functional.forward can be used.
:)
> The following code illustrates the difference.
>
> import std.traits;
> import std.functional : forward;
>
> /**
> Evaluates true if `func` is callable with arguments `args`.
> Can only be used as a function template constraint.
> */
> enum isCallableWith(alias func, args...) =
> is(typeof(func(forward!args)));
// That's cool! Much shorter, as I thought.
>
> // Your original A
> struct A(alias func) if (isCallable!func)
> {
> auto opCall(Args...)(Args args) if (__traits(compiles,
> func(args)))
> {
> // all arguments are copied, any "ref/out" semantics
> are lost
> return func(args);
> }
> }
>
> // Modified to forward arguments
> struct B(alias func) if (isCallable!func)
> {
> // auto ref: preserve lvalues
> auto opCall(Args...)(auto ref Args args) if
> (isCallableWith!(func, args))
> {
> // forward: preserve lvalues
> return func(forward!args);
> }
> }
>
> struct S
> {
> auto opCall() { return 42; }
> auto opCall(int i) { return 42; }
> // Note: parameter passed by reference!
> auto opCall(out float f) { f = 42.0f; }
> }
>
> void main()
> {
> S s;
>
> {
> A!s c;
> int i = 4;
> static assert(is(typeof(c(i))));
> static assert(is(typeof(c(4))));
> static assert(is(typeof(c())));
>
> assert(c(i) == 42);
> assert(c(4) == 42);
> assert(c() == 42);
> // Should pass but doesn't.
> //static assert(!is(typeof(c(3.5f))));
> float f;
> static assert(is(typeof(c(f))));
> c(f);
> // Will assert:
> assert(f == 42.0f);
> }
>
> {
> B!s c;
> int i = 4;
> static assert(is(typeof(c(i))));
> static assert(is(typeof(c(4))));
> static assert(is(typeof(c())));
>
> assert(c(i) == 42);
> assert(c(4) == 42);
> assert(c() == 42);
> // Passes
> static assert(!is(typeof(c(3.5f))));
> float f;
> static assert(is(typeof(c(f))));
> c(f);
> // Won't assert
> assert(f == 42.0f);
> }
> }
Ha, that is exactly what I am after :)
Thanks a lot!
More information about the Digitalmars-d-learn
mailing list