March 09, 2010
To try the new operators I have created this helper that works:


auto operators(string[] items...) {
    struct Bunch {
        string[] items;

        bool opBinaryRight(string s:"in")(string item) {
            foreach (el; items)
                if (el == item)
                    return true;
            return false;
        }
    }

    return Bunch(items);
}

struct Foo {
    int x;

    this(int xx) { this.x = xx; }

    // Foo opBinary(string s)(Foo other) if (s in ["+", "-", "*", "/"]) {
    Foo opBinary(string s)(Foo other) if (s in operators("+", "-", "*", "/")) {
        mixin("return Foo(this.x " ~ s ~ " other.x);");
    }
}



But I don't like that operators(), I'd like a more generic bunch() that works at compile time. I have found a long series of bugs and limits trying to do it... :-)

This works at run-time only:

auto bunch(Types...)(Types itemsTuple) {
    static struct Bunch {
        Types items;
        bool opBinaryRight(string s:"in")(string item) {
            foreach (el; items)
                if (el == item)
                    return true;
            return false;
        }
    }

    return Bunch(itemsTuple);
}


This never works, I don't know why:

auto bunch(Types...)(Types itemsTuple) {
    struct Bunch {
        bool opBinaryRight(string s:"in")(string item) {
            foreach (el; itemsTuple)
                if (el == item)
                    return true;
            return false;
        }
    }

    return Bunch();
}


Maybe there is no way to have a reference to the input argument tuple in a nonstatic nested struct, but this works:

import std.stdio: writeln;

auto equals_two(Types...)(Types items) {
    bool foo() {
        return items[0] == items[1];
    }
    return &foo;
}

void main() {
    writeln(equals_two(1, 2)());
}


Notes:

opBinaryRight("in") for arrays is useful even at compile time :-)

While doing those experiments I have seen this is not supported, because T must be known:
auto bunch(T)(T[] items...) {

Bye,
bearophile