templatized delegate

ag0aep6g via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Tue May 23 11:14:34 PDT 2017


On 05/23/2017 01:30 PM, Alex wrote:
> And no, I can't pass it by adress, as I don't know apriori, whether the 
> very parameter which gets the random generator is already a part of the 
> variadic parameters, or a well defined ref parameter.

A (run-time) variadic delegate isn't flexible like that. When you have a 
`void delegate(...)`, then there are no non-variadic parameters. You 
know both in the caller and in the callee that passing by ref is not an 
option. So you can define that uncopyable types are passed by pointer.

Going this route means you have to make all your delegates variadic 
(this might be annoying). A.fun can remain a variadic template. It can 
also have ref parameters, but then you have to detect uncopyable types 
and pass pointers to the delegate.

Something like this:

----
import core.vararg;
import std.meta: AliasSeq, staticMap;
import std.traits: isCopyable;

struct A
{
     void delegate(...) dg;
     auto fun(T, U ...)(T t, auto ref U u)
     {
         template UncopyableToPointer(T)
         {
             static if (!isCopyable!T) alias UncopyableToPointer = T*;
             else alias UncopyableToPointer = T;
         }
         alias U2 = staticMap!(UncopyableToPointer, U);

         U2 u2;
         foreach (i, E; U)
         {
             static if (!isCopyable!E) u2[i] = &u[i];
             else u2[i] = u[i];
         }

         return dg(t, u2);
     }
}

struct SomeStructThatIsNotCopyable
{
     @disable this(this);
}

void main()
{
     void dlg(...)
     {
         import std.stdio;
         foreach (i, t; _arguments)
         {
             foreach (T; AliasSeq!(int, string,
                 SomeStructThatIsNotCopyable*))
             {
                 if (t == typeid(T))
                 {
                     static if (is(T : U*, U) && !isCopyable!U)
                     {
                         write("uncopyable type");
                     }
                     else write(_argptr.va_arg!T);
                 }
             }
             /* otherwise: don't know how to handle the type */
             write(" ");
         }
         writeln();
     }

     auto a = A(&dlg);
     SomeStructThatIsNotCopyable s;
     a.fun(5, "a", /* by ref: */ s, /* or by pointer: */ &s);
}
----

That's not exactly pretty, of course. Both A.fun and the delegate are 
quite complicated. But it might be workable, if run-time variadics are 
acceptable.

I wouldn't be surprised if the problem can be solved more elegantly. But 
I don't see how at the moment.


More information about the Digitalmars-d-learn mailing list