Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
106 changes: 106 additions & 0 deletions std/traits.d
Original file line number Diff line number Diff line change
Expand Up @@ -5027,6 +5027,112 @@ unittest
//static assert( isAssociativeArray!EAA);
}


// Returns the element type of an array.
private alias _ArrayElementType(T : T[]) = T;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's strange that this matches for static array types. It's certainly not regular; if it's not a bug, it's an undocumented special case. I'm not sure if relying on this behaviour is a good idea, but the only code that would break is Phobos code so it's not a big deal.



/**
Gets the rank (number of dimensions) of a static array type.

If $(D T) isn't a static array assumes it to be a $(I zero-dimensional)
static array with single element and returns zero.
*/
template staticArrayDims(T)
{
static if(isStaticArray!T)
enum staticArrayDims = 1 + staticArrayDims!(_ArrayElementType!T);
else
enum staticArrayDims = 0;
}

///
unittest
{
static assert(staticArrayDims!int == 0);
static assert(staticArrayDims!(int[]) == 0);
static assert(staticArrayDims!(int[0]) == 1);
static assert(staticArrayDims!(int[7][8]) == 2);
static assert(staticArrayDims!(int[0][]) == 0);
static assert(staticArrayDims!(int[][0]) == 1);
}

unittest
{
static assert(staticArrayDims!string == 0);
static assert(staticArrayDims!(int[0][0]) == 2);
}


/**
Gets the element type of the innermost array in a multidimensional static array type.
Considers $(D T) to be an $(D n)-dimensional static array type.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this not statically enforced in the signature of the template?


Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've seen such functions for multidimensional arrays in other libs. Never found a good use for them.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thought more about this and a type InnermostType that goes all the way through static and dynamic dimension may be marginally useful and generic enough for inclusion in stdlib.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As above I see no practical need to mix static and dynamic arrays. Again, our opinions are opposite.

If $(D T) isn't a static array assumes it to be a $(I zero-dimensional)
static array with single element and returns $(D T).
*/
template MultidimStaticArrayElementType(T, size_t n = staticArrayDims!T)
{
static assert(staticArrayDims!T >= n, "Not enough static array dimensions");
static if(n)
alias MultidimStaticArrayElementType = MultidimStaticArrayElementType!(_ArrayElementType!T, n-1);
else
alias MultidimStaticArrayElementType = T;
}

///
unittest
{
static assert(is(MultidimStaticArrayElementType!int == int));
static assert(is(MultidimStaticArrayElementType!(int[]) == int[]));
static assert(is(MultidimStaticArrayElementType!(int[0]) == int));
static assert(!__traits(compiles, MultidimStaticArrayElementType!(int[7][8], 3)));
static assert(is(MultidimStaticArrayElementType!(int[7][8]) == int));
static assert(is(MultidimStaticArrayElementType!(int[7][8], 1) == int[7]));
static assert(is(MultidimStaticArrayElementType!(int[7][8], 0) == int[7][8]));
static assert(is(MultidimStaticArrayElementType!(int[0][]) == int[0][]));
static assert(is(MultidimStaticArrayElementType!(int[][0]) == int[]));
}

unittest
{
static assert(is(MultidimStaticArrayElementType!string == string));
}


/**
Calculates the total element count of a multidimensional static array.
Considers $(D T) to be an $(D n)-dimensional static array type.

If $(D T) isn't a static array assumes it to be a $(I zero-dimensional)
static array with single element and returns 1.
*/
template multidimStaticArrayElementCount(T, size_t n = staticArrayDims!T)
{
static assert(staticArrayDims!T >= n, "Not enough static array dimensions");
enum multidimStaticArrayElementCount = T.sizeof / MultidimStaticArrayElementType!(T, n).sizeof;
}

///
unittest
{
static assert(multidimStaticArrayElementCount!int == 1);
static assert(multidimStaticArrayElementCount!(int[]) == 1);
static assert(multidimStaticArrayElementCount!(int[0]) == 0);
static assert(!__traits(compiles, multidimStaticArrayElementCount!(int[7][8], 3)));
static assert(multidimStaticArrayElementCount!(int[7][8]) == 7 * 8);
static assert(multidimStaticArrayElementCount!(int[7][8], 1) == 8);
static assert(multidimStaticArrayElementCount!(int[7][8], 0) == 1);
static assert(multidimStaticArrayElementCount!(int[0][]) == 1);
static assert(multidimStaticArrayElementCount!(int[][0]) == 0);
}

unittest
{
static assert(multidimStaticArrayElementCount!string == 1);
}


template isBuiltinType(T)
{
enum isBuiltinType = is(BuiltinTypeOf!T) && !isAggregateType!T;
Expand Down