May 23, 2017
On Tuesday, 23 May 2017 at 11:05:09 UTC, Stanislav Blinov wrote:
> void variadic(Args...)(auto ref Args args) { /* ... */ }
>
> This infers whether you pass lvalues or rvalues. If passing further down the chain of such calls is needed, one can use std.functional : fowrard :

yes...

>
> void variadic(Args...)(auto ref Args args) {
>     import std.functional : forward;
>     doStuff(forward!args);
> }
>
> void doStuff(Args...)(auto ref Args args) {
>     /* ... */
> }
>
> 'forward' aliases ref arguments (i.e. passed lvalues) and moves value arguments (i.e. passed rvalues).
>
> If a value is not copyable, it may be move-able (check the docs though, it may not be that either).
>
> void fun(Args...)(auto ref Args args) { /*...*/ }

yes...

> import std.algorithm : move;
>
> auto a = NonCopyable(42);
>
> fun(move(a));
> // or:
> func(NonCopyable(42));

the problem, that I have is, that I would like to use the templated approach, but I don't have the function, but only a delegate, so:

template(T, U...)
{
    void delegate(ref T neededInput, ref U ignoredInput) dgPtr;
}

Not sure, if this is possible to handle at all...
May 23, 2017
On Tuesday, 23 May 2017 at 11:45:13 UTC, Alex wrote:
> On Tuesday, 23 May 2017 at 11:05:09 UTC, Stanislav Blinov wrote:
>> void variadic(Args...)(auto ref Args args) { /* ... */ }
>>
>> This infers whether you pass lvalues or rvalues. If passing further down the chain of such calls is needed, one can use std.functional : fowrard :
>
> yes...
>
>>
>> void variadic(Args...)(auto ref Args args) {
>>     import std.functional : forward;
>>     doStuff(forward!args);
>> }
>>
>> void doStuff(Args...)(auto ref Args args) {
>>     /* ... */
>> }
>>
>> 'forward' aliases ref arguments (i.e. passed lvalues) and moves value arguments (i.e. passed rvalues).
>>
>> If a value is not copyable, it may be move-able (check the docs though, it may not be that either).
>>
>> void fun(Args...)(auto ref Args args) { /*...*/ }
>
> yes...
>
>> import std.algorithm : move;
>>
>> auto a = NonCopyable(42);
>>
>> fun(move(a));
>> // or:
>> func(NonCopyable(42));
>
> the problem, that I have is, that I would like to use the templated approach, but I don't have the function, but only a delegate, so:
>
> template(T, U...)
> {
>     void delegate(ref T neededInput, ref U ignoredInput) dgPtr;
> }
>
> Not sure, if this is possible to handle at all...

Ah, now I think I get it. You want to store a single delegate that could be called with different sets of arguments? No, you can't do that: you need an actual delegate instance, and for that, you need to know the signature, at least when instantiating C.
May 23, 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.
May 23, 2017
On Tuesday, 23 May 2017 at 18:14:34 UTC, ag0aep6g wrote:
> 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.

That's cool :)
but anyway, even if I have such params, there are not much of them, so it just a minor semantic issue to explicitely name them and their types instead of showing, that they are passed but not used inside dlg.
And thanks a lot to all for great ideas :)
May 23, 2017
On Tuesday, 23 May 2017 at 16:38:14 UTC, Stanislav Blinov wrote:
> Ah, now I think I get it. You want to store a single delegate that could be called with different sets of arguments? No, you can't do that: you need an actual delegate instance, and for that, you need to know the signature, at least when instantiating C.

Yes :)
or, just to differentiate between the used and unused parameters, without loosing their types and attributes.
But that's a minor problem, the solution with full signature

https://forum.dlang.org/post/ekbpjsuyqprusyasmjsm@forum.dlang.org#post-svvgcrymplmyondhuogt:40forum.dlang.org

works also well, as the effort to name everything is not so big in my case...
1 2
Next ›   Last »