Bug or am I getting things wrong

John Colvin via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Thu Jan 7 01:31:10 PST 2016


On Thursday, 7 January 2016 at 07:51:05 UTC, Q. Schroll wrote:
> In the listing below the commented line should do exactly the 
> same thing as the one above.
>
> /// DimArr!(i, T) ==> T[][]...[] i times.
> template DimArr(size_t i, T)
> {
>     static if (i == 0)  alias DimArr = T;
>     else                alias DimArr = DimArr!(i - 1, T)[];
> }
>
>
> struct Array(T, size_t rk)
>     if (rk > 1)
> {
>     private size_t[rk] dims;
>     /+ ... +/
>     auto toNestedArray() const
>     {
>         import std.range : iota;
>         import std.format : format;
>         enum dimsIndexed = `%(dims[%d]%|, 
> %)`.format(dims.length.iota);
>         auto result = mixin(`new DimArr!(rk, T)(` ~ dimsIndexed 
> ~ `)`);
>      // auto result = new DimArr!(rk, T)(mixin(dimsIndexed)));
>         /+ ... +/
>         return result;
>     }
> }
>
> The one above does exactly what I want, but the lower one only 
> uses the last dimension for some reason. I found out by using 
> these pragmas
>
>     pragma(msg, "'", dimsIndexed, "'");
>     pragma(msg, ( new DimArr!(rk, T) ( mixin(dimsIndexed) ) 
> ).stringof);
>
> Can someone please tell me what I'm getting wrong here, or is 
> this a bug?

Wow, that's a new reason to hate the comma operator even more 
than I did before!

The expression that you are mixing in is actually a sequence of 
sub-expressions seperated by the comma operator, which means each 
expression is evaluated and the last one is returned. Remember, 
mixins are not textual substitution like C macros. Normally 
speaking you get error messages if you forget that, and that's 
ok, but here the evil comma operator made a mess of things.

Here's one way to achieve what you want:

/// DimArr!(i, T) ==> T[][]...[] i times.
template DimArr(size_t i, T)
{
     static if (i == 0)
		alias DimArr = T;
     else
		alias DimArr = DimArr!(i - 1, T)[];
}

template Repeat(T, size_t N)
{
	import std.meta : AliasSeq;
	static if (N == 0)
		alias Repeat = AliasSeq!();
	else
		alias Repeat = AliasSeq!(T, Repeat!(T, N-1));
}

auto toTuple(T, size_t N)(T[N] arr)
{
	import std.typecons : Tuple;
	import std.traits : Unqual;
	Tuple!(Repeat!(Unqual!T, N)) tup;
	foreach(i, _; tup)
		tup[i] = arr[i];
	return tup;
}

struct Array(T, size_t rk)
     if (rk > 1)
{
     private size_t[rk] dims;
     /+ ... +/
     auto toNestedArray() const
     {
         auto result = new DimArr!(rk, T)(dims.toTuple.expand);
         /+ ... +/
         return result;
     }
}


More information about the Digitalmars-d-learn mailing list