www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - question with compile-time reflection

reply "Zhenya" <zheny list.ru> writes:
Hi!

this code fails with message:NDimensionalArray.doIndex(Array) if 
(is(Array _ : NDimensionalArrayType!(T,s),const(int[]) s)) cannot 
deduce template function from argument types 
!()(int[2u][2u],const(int[]))

Tell me please,am I wrong?
And if yes,what should I change to make it work?

template NDimensionalArrayType(T,alias size)
	if(is(typeof(size) _ : const int[]) && size.length > 0)
{
	static if(size.length > 1)
		alias NDimensionalArrayType!(T,size[1..$])[size[0]] 
NDimensionalArrayType;
	else
		alias T[size[0]] NDimensionalArrayType;
}

struct NDimensionalArray(T,alias size)
{
	private NDimensionalArrayType!(T,size) m_array;
	static ref T doIndex(Array)(Array array,const int[] index) //HERE
		if(is(Array _ : NDimensionalArrayType!(T,s),const int[] s))
	{
		assert(index.length == s.length);
		if(index.length == 1)
			return array[index[0]];
		else
			return doIndex(array[index[0]],index[1..$]);
	}
	ref T opIndex(const int[] index)
	{
		return doIndex(m_array,index);
	}
	alias m_array this;
}

void main()
{
	NDimensionalArray!(int,[2,2]) array;
}
Mar 09 2013
next sibling parent "Rob T" <alanb ucora.com> writes:
template NDimensionalArrayType(T,alias size)

I think your use of "alias size" is incorrect.

See http://dlang.org/declaration.html

--rt
Mar 09 2013
prev sibling parent reply "Ivan Kazmenko" <gassa mail.ru> writes:
 this code fails with message:NDimensionalArray.doIndex(Array) 
 if (is(Array _ : NDimensionalArrayType!(T,s),const(int[]) s)) 
 cannot deduce template function from argument types 
 !()(int[2u][2u],const(int[]))

 Tell me please,am I wrong?
 And if yes,what should I change to make it work?
I'm no D expert, but here's what I got. 1. One problem is returning the wrong type from doIndex. When the condition "if(index.length == 1)" is false, the subsequent line is still compiled but fails to return a "ref T" since "array[index[0]]" is an array of T, not a T. The correct way (and better for performance, too) would be a compile-time "static if" there, like in the code below. (I don't quite get the syntax of the template constraint for doIndex, so I've just commented that out for now.) 2. The next problem is that fixed-size arrays obey value semantics, so they should be passed by reference and not by value. Here's what works for me (DMD 2.062): ----- import std.stdio; template NDimensionalArrayType(T,alias size) if(is(typeof(size) _ : const int[]) && size.length > 0) { static if(size.length > 1) alias NDimensionalArrayType!(T,size[1..$])[size[0]] NDimensionalArrayType; else alias T[size[0]] NDimensionalArrayType; } struct NDimensionalArray(T,alias size) { private NDimensionalArrayType!(T,size) m_array; static ref T doIndex(Array)(ref Array array,const int[] index) //HERE // if(is(Array _ : NDimensionalArrayType!(T,s),const int[] s)) { // assert(index.length == s.length); assert(index.length <= size.length); debug {writefln("doIndex (%s, %s = %s)", typeof(array).stringof, typeof(index).stringof, index);} static if(is(Array : T[])) { assert(index.length == 1); return array[index[0]]; } else { assert(index.length > 1); return doIndex(array[index[0]],index[1..$]); } } ref T opIndex(const int[] index) { return doIndex(m_array,index); } alias m_array this; } void main() { NDimensionalArray!(int,[5,2]) array; array[[4,1]] = 1; assert(array[[4,1]] == 1); } ----- With the debug mode on, it successfully prints the following: ----- doIndex (int[2u][5u], const(int[]) = [4, 1]) doIndex (int[2u], const(int[]) = [1]) doIndex (int[2u][5u], const(int[]) = [4, 1]) doIndex (int[2u], const(int[]) = [1]) ----- On a side note, this still looks like too much effort to do one opIndex in terms of performance. I doubt that any current compiler would optimize all that into a simple multiply + bounds-check + add loop. ----- Ivan Kazmenko.
Mar 09 2013
parent reply "Zhenya" <zheny list.ru> writes:
On Saturday, 9 March 2013 at 23:05:56 UTC, Ivan Kazmenko wrote:
 this code fails with message:NDimensionalArray.doIndex(Array) 
 if (is(Array _ : NDimensionalArrayType!(T,s),const(int[]) s)) 
 cannot deduce template function from argument types 
 !()(int[2u][2u],const(int[]))

 Tell me please,am I wrong?
 And if yes,what should I change to make it work?
I'm no D expert, but here's what I got. 1. One problem is returning the wrong type from doIndex. When the condition "if(index.length == 1)" is false, the subsequent line is still compiled but fails to return a "ref T" since "array[index[0]]" is an array of T, not a T. The correct way (and better for performance, too) would be a compile-time "static if" there, like in the code below. (I don't quite get the syntax of the template constraint for doIndex, so I've just commented that out for now.) 2. The next problem is that fixed-size arrays obey value semantics, so they should be passed by reference and not by value. Here's what works for me (DMD 2.062): ----- import std.stdio; template NDimensionalArrayType(T,alias size) if(is(typeof(size) _ : const int[]) && size.length > 0) { static if(size.length > 1) alias NDimensionalArrayType!(T,size[1..$])[size[0]] NDimensionalArrayType; else alias T[size[0]] NDimensionalArrayType; } struct NDimensionalArray(T,alias size) { private NDimensionalArrayType!(T,size) m_array; static ref T doIndex(Array)(ref Array array,const int[] index) //HERE // if(is(Array _ : NDimensionalArrayType!(T,s),const int[] s)) { // assert(index.length == s.length); assert(index.length <= size.length); debug {writefln("doIndex (%s, %s = %s)", typeof(array).stringof, typeof(index).stringof, index);} static if(is(Array : T[])) { assert(index.length == 1); return array[index[0]]; } else { assert(index.length > 1); return doIndex(array[index[0]],index[1..$]); } } ref T opIndex(const int[] index) { return doIndex(m_array,index); } alias m_array this; } void main() { NDimensionalArray!(int,[5,2]) array; array[[4,1]] = 1; assert(array[[4,1]] == 1); } ----- With the debug mode on, it successfully prints the following: ----- doIndex (int[2u][5u], const(int[]) = [4, 1]) doIndex (int[2u], const(int[]) = [1]) doIndex (int[2u][5u], const(int[]) = [4, 1]) doIndex (int[2u], const(int[]) = [1]) ----- On a side note, this still looks like too much effort to do one opIndex in terms of performance. I doubt that any current compiler would optimize all that into a simple multiply + bounds-check + add loop. ----- Ivan Kazmenko.
Thank you very much for your time) Your answer is very useful.
Mar 09 2013
parent reply "Zhenya" <zheny list.ru> writes:
Although of course I would want to know what's wrong with 
constrait,because it protect doArray against incorrect using.
I don't worry about effiency very much,I just wanted to right 
n-dimensional tree of intervals.And for doing it I needed 
n-dimensional array with opIndex like it.
Mar 09 2013
parent reply "Zhenya" <zheny list.ru> writes:
On Saturday, 9 March 2013 at 23:40:25 UTC, Zhenya wrote:
 Although of course I would want to know what's wrong with 
 constrait,because it protect doArray against incorrect using.
 I don't worry about effiency very much,I just wanted to right 
 n-dimensional tree of intervals.And for doing it I needed 
 n-dimensional array with opIndex like it.
sorry for my english(
Mar 09 2013
parent reply "Rob T" <alanb ucora.com> writes:
template NDimensionalArrayType(T,alias size)

I'm wondering what "alias size" does? I can't find that form 
documented anywhere, but it seems to be valid.

Thanks.

--rt
Mar 10 2013
next sibling parent reply "Zhenya" <zheny list.ru> writes:
On Monday, 11 March 2013 at 00:10:46 UTC, Rob T wrote:
 template NDimensionalArrayType(T,alias size)

 I'm wondering what "alias size" does? I can't find that form 
 documented anywhere, but it seems to be valid.

 Thanks.

 --rt
It's just a little hack for known bug - only string and integer value can be passed into template. size is array,and it's really size of n-dimensional array,every element matches its dimension.
Mar 10 2013
parent "Zhenya" <zheny list.ru> writes:
And since alias can represent any symbol,i think that it's 
correct usage.
Mar 10 2013
prev sibling parent reply "anonymous" <anonymous example.com> writes:
On Monday, 11 March 2013 at 00:10:46 UTC, Rob T wrote:
 template NDimensionalArrayType(T,alias size)

 I'm wondering what "alias size" does? I can't find that form 
 documented anywhere, but it seems to be valid.
http://dlang.org/template.html#TemplateAliasParameter
Mar 10 2013
parent "Rob T" <alanb ucora.com> writes:
On Monday, 11 March 2013 at 00:26:25 UTC, anonymous wrote:
 On Monday, 11 March 2013 at 00:10:46 UTC, Rob T wrote:
 template NDimensionalArrayType(T,alias size)

 I'm wondering what "alias size" does? I can't find that form 
 documented anywhere, but it seems to be valid.
http://dlang.org/template.html#TemplateAliasParameter
I actually read that page, but somehow missed this description or more likely did not understand what it meant. I think I could spend 10 years reading up on D and still not fully know everything about it. --rt
Mar 10 2013