On Wednesday, 31 May 2017 at 21:02:07 UTC, jmh530 wrote:
On Wednesday, 31 May 2017 at 19:22:18 UTC, Stefan Koch wrote:

You could also use string mixins.
Which will be more efficient then recursion.

I try to avoid string mixins unless I can't help it. Nevertheless, I made an effort to try to get it to work and below seems to be working. I still have to use some recursion to generate the string.

The downside is that this version can't be @nogc, correct?


One advantage of the mixin version is that I don't have to explicitly get the type of the result. In ag0aep6g's example, it works easily enough for arrays, but if the indexing is more complicated, then it becomes a pain to get the correct types.

I struggled a little to get it @nogc, but eventually got it there by changing the helper code to free-standing functions that use enums to force CTFE. The code is below:

private
{
        const(char[]) opIndex_i(size_t i)() @nogc
        {
                return "this.underlying[" ~ i.stringof ~ "][slices[" ~
                                                                        i.stringof ~ 
"]]";
        }
                
        const(char[]) GenResult(alias f, T...)() @nogc
        {
                const(char[]) GenParens(U...)() @nogc
                {
                        static if (U.length > 0)
                        {
                                static if (U.length == 1)
                                {
                                        enum result = f!(U.length - 1);
                                }
                                else static if (U.length > 1)
                                {
enum result = GenParens!(U[0 .. $ - 1]) ~ ", " ~ f!(U.length - 1);
                                }
                                return result;
                        }
                }
                
                enum parens = GenParens!(T);
                return "foo!(Names)(" ~ parens ~ ")";
        }
}

struct Foo(T...)
{
        alias U = Tuple!T;
        U underlying;
        alias underlying this;
        
        alias Names = U.fieldNames;
        alias Types = U.Types;
        
        /// Alternate access to tuple
        auto index(size_t dimension)() const @property
        {
                return underlying[dimension];
        }
        
        auto ref opIndex(Slices...)(Slices slices) @nogc
        if (Slices.length == Types.length)
    {
                return mixin(GenResult!(opIndex_i, Slices));
    }
}

Reply via email to