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