View mode: basic / threaded / horizontal-split · Log in · Help
August 09, 2010
Cannot use local xxx as parameter to non-global template.
I'm new, so this is most certainly my fault I guess, but I cannot 
understand the error message...
I wish to slice an array and store the slices in a tuple.

auto partitionArray(T)(T[] array, int offset, int len)
{
	auto pre = array[0 .. offset];
	auto slice = array[offset .. offset+len];
	auto post = array[offset+len .. $];
	
	return Tuple!(pre, slice, post);
}
unittest
{
	auto val = partitionArray([1,2,3,4], 1, 2);
}

typecons.d(255): Error: template instance cannot use local 'post' as 
parameter to non-global template A(U...)
August 10, 2010
Re: Cannot use local xxx as parameter to non-global template.
simendsjo wrote:

> I'm new, so this is most certainly my fault I guess, but I cannot
> understand the error message...
> I wish to slice an array and store the slices in a tuple.
> 
> auto partitionArray(T)(T[] array, int offset, int len)
> {
> auto pre = array[0 .. offset];
> auto slice = array[offset .. offset+len];
> auto post = array[offset+len .. $];
> 
> return Tuple!(pre, slice, post);
> }
> unittest
> {
> auto val = partitionArray([1,2,3,4], 1, 2);
> }
> 
> typecons.d(255): Error: template instance cannot use local 'post' as
> parameter to non-global template A(U...)

Try this:

auto partitionArray(T)(T[] array, int offset, int len)
{
       auto pre = array[0 .. offset];
       auto slice = array[offset .. offset+len];
       auto post = array[offset+len .. $];
       
       return tuple(pre, slice, post);
}
unittest
{
       auto val = partitionArray([1,2,3,4], 1, 2);
}

Explanation: In D you can pass a template a symbol as a parameter, and the 
parameter will alias simply to that symbol itself. So here you try to 
instantiate a Tuple with three local variables as the compile time parameters. 
The tuple function will infer the types of them instead and wrap them up for 
you.

Instantiating a template with local variables is actually possible, but only if 
the template is declared at global scope, which isn't the case here. It is very 
useful for nested functions, you even instantiate it with anonymous delegates:

template Foo(alias sym)
{
   alias sym Foo;
}

unittest
{
   int number = 1;
   alias Foo!number FooNumber;
   FooNumber++;
   assert(number == 2);
   assert(__traits(identifier, FooNumber) == "number");
   
   alias Foo!( { writeln(number); } ) PrintNumber;
   PrintNumber();
}
Top | Discussion index | About this forum | D home