Thread overview
Runtime error trying to call opCall on variant array of objects
Dec 24, 2016
aliak
Dec 24, 2016
Ali Çehreli
Dec 25, 2016
aliak
December 24, 2016
Hey, so I'm trying to make an variant array of objects (each one has an opCall defined) and then call each of them in succession. It doesn't seem to be working. The error I get is:

"Cannot apply `()' to a value of type `Command!(__lambda1, int)". I think it's failing when it checks for "!isFunctionPointer!A && !isDelegate!A".

Here's the bit of code:

struct Command(alias fun, Args...) {
    Args args;
    this(Args args) {
        args = args;
    }
    auto opCall() {
        return fun(args);
    }
}

auto command(alias fun, Args...)(Args args) {
    return Command!(fun, Args)(args);
}

void main() {
    auto commands = variantArray(
        command!(a => a + 1)(1),
        command!(a => a + 2)(1),
        command!(a => a + 3)(1),
    );

   // commands.each!(a => a()); // <-- crashes runtime

    typeid(commands[0]).writeln; // std.variant.VariantN!32LU.VariantN

    auto cmd = command!(a => a + 1)(1);
    typeid(cmd).writeln; // scratchpad.main.Command!(__lambda4, int).Command
}

Is there a way to do what I'm trying to do?

Cheers!
December 24, 2016
On 12/24/2016 08:36 AM, aliak wrote:

> "Cannot apply `()' to a value of type `Command!(__lambda1, int)". I
> think it's failing when it checks for "!isFunctionPointer!A &&
> !isDelegate!A".

Storing delegates is a workaround. Three notes in the code:

// (1) Added imports
import std.variant;
import std.stdio;
import std.algorithm;

struct Command(alias fun, Args...) {
    Args args;
    this(Args args) {
        this.args = args;    /* (2) args = args was a common mistake.
                              * dmd, please warn about this one.
                              * (I think there is a bug about that.)
                              */
    }
    auto opCall() {
        writefln("opCall called for %s", args);
        return fun(args);
    }
}

auto command(alias fun, Args...)(Args args) {
    auto c = Command!(fun, Args)(args);
    writefln("Created %s", c);
    // (3) Workaround: Storing delegates, not Command instances.
    return () => c();
}

void main() {
    auto commands = variantArray(
        command!(a => a + 1)(1),
        command!(a => a + 2)(1),
        command!(a => a + 3)(1),
    );

    commands.each!(a => a());

    typeid(commands[0]).writeln; // std.variant.VariantN!32LU.VariantN

    auto cmd = command!(a => a + 1)(1);
    typeid(cmd).writeln; // scratchpad.main.Command!(__lambda4, int).Command
}

Alid
December 25, 2016
On Saturday, 24 December 2016 at 23:06:25 UTC, Ali Çehreli wrote:
>     auto c = Command!(fun, Args)(args);
>     writefln("Created %s", c);
>     // (3) Workaround: Storing delegates, not Command instances.
>     return () => c();

Ah, yes. Nice work around :)

Thankies!