Jump to page: 1 2
Thread overview
Templates array detection
Dec 12, 2012
Cube
Dec 12, 2012
bearophile
Dec 12, 2012
Cube
Dec 12, 2012
Cube
Dec 12, 2012
Ali Çehreli
Dec 12, 2012
Cube
Dec 12, 2012
Ali Çehreli
Dec 12, 2012
bearophile
Dec 12, 2012
ixid
Dec 12, 2012
bearophile
Dec 12, 2012
ixid
Dec 12, 2012
bearophile
December 12, 2012
Hi,

I'm having a problem getting templates to work correctly.
I want to handle arrays differently, but when I try to compile the following example code it says it matches more than 1 template. What is the correct way to do this?


--
void main()
{
    foo(1);
    foo([1,1]);
}

void foo(T)(T t)
{
    writeln(t);
}

void foo(T)(T[] t)
{
    for(int i = 0; i < t.length; i++)
        writeln(t[i]);
}
--
December 12, 2012
Cube:

> I'm having a problem getting templates to work correctly.
> I want to handle arrays differently, but when I try to compile the following example code it says it matches more than 1 template. What is the correct way to do this?
>
>
> --
> void main()
> {
>     foo(1);
>     foo([1,1]);
> }
>
> void foo(T)(T t)
> {
>     writeln(t);
> }
>
> void foo(T)(T[] t)
> {
>     for(int i = 0; i < t.length; i++)
>         writeln(t[i]);
> }
> --

In general D templates refuse ambiguity. So to fix your situation you have to state that the T in your first foo overload is not an array:

import std.stdio, std.traits;

void main()
{
    foo(1);
    foo([1, 1]);
}

void foo(T)(T t) if (!isArray!T)
{
    writeln(t);
}

void foo(T)(T[] t)
{
    foreach (ti; t)
        writeln(ti);
}


Bye,
bearophile
December 12, 2012
On Wednesday, 12 December 2012 at 12:34:34 UTC, bearophile wrote:
> Cube:
>
>> I'm having a problem getting templates to work correctly.
>> I want to handle arrays differently, but when I try to compile the following example code it says it matches more than 1 template. What is the correct way to do this?
>>
>>
>> --
>> void main()
>> {
>>    foo(1);
>>    foo([1,1]);
>> }
>>
>> void foo(T)(T t)
>> {
>>    writeln(t);
>> }
>>
>> void foo(T)(T[] t)
>> {
>>    for(int i = 0; i < t.length; i++)
>>        writeln(t[i]);
>> }
>> --
>
> In general D templates refuse ambiguity. So to fix your situation you have to state that the T in your first foo overload is not an array:
>
> import std.stdio, std.traits;
>
> void main()
> {
>     foo(1);
>     foo([1, 1]);
> }
>
> void foo(T)(T t) if (!isArray!T)
> {
>     writeln(t);
> }
>
> void foo(T)(T[] t)
> {
>     foreach (ti; t)
>         writeln(ti);
> }
>
>
> Bye,
> bearophile

Hi,

I eventually modified my code to:
--
void main()
{
    foo(1);
    foo([1,1]);
}

void foo(T)(T t)
{
	bar!(T)(t);
}

void bar(T)(T t)
{
    writeln(t+1);
}

void bar(T: T[])(T[] t)
{
    for(int i = 0; i < t.length; i++)
        writeln(t[i]);
}
--
Essentially I added a helper function that added !(T).
What, if any, is the benefit of either approach?


And a similar issue, what if I have a struct:
--
struct Data(T)
{
	int elem = 3;
}

void main()
{
    foo(1);
    foo([1,1]);

    foo(new Data!(int));
    foo(new Data!(float));
}

void foo(T)(T t)
{
	bar!(T)(t);
}

void bar(T)(T t)
{
    writeln(t+1);
}

void bar(T: T[])(T[] t)
{
    for(int i = 0; i < t.length; i++)
        writeln(t[i]);
}
--

And I want to add this to the rest of the program. Where/how can I direct the Data's to separate functions?

Thanks :)
December 12, 2012
On Wednesday, 12 December 2012 at 12:34:34 UTC, bearophile wrote:
> Cube:
>
>> I'm having a problem getting templates to work correctly.
>> I want to handle arrays differently, but when I try to compile the following example code it says it matches more than 1 template. What is the correct way to do this?
>>
>>
>> --
>> void main()
>> {
>>    foo(1);
>>    foo([1,1]);
>> }
>>
>> void foo(T)(T t)
>> {
>>    writeln(t);
>> }
>>
>> void foo(T)(T[] t)
>> {
>>    for(int i = 0; i < t.length; i++)
>>        writeln(t[i]);
>> }
>> --
>
> In general D templates refuse ambiguity. So to fix your situation you have to state that the T in your first foo overload is not an array:
>
> import std.stdio, std.traits;
>
> void main()
> {
>     foo(1);
>     foo([1, 1]);
> }
>
> void foo(T)(T t) if (!isArray!T)
> {
>     writeln(t);
> }
>
> void foo(T)(T[] t)
> {
>     foreach (ti; t)
>         writeln(ti);
> }
>
>
> Bye,
> bearophile

It's a pity it doesn't see T[] as the best fit and go with it on that basis.
December 12, 2012
ixid:

> It's a pity it doesn't see T[] as the best fit and go with it on that basis.

It's not a pity, it's a good design. "Best fit" makes language&compiler complex, less predictable for the programmer, etc.

Bye,
bearophile
December 12, 2012
Better example code for my other problem. How can I make the 3rd foo work on  Datas?

--
struct Data(T)
{
	T elem;
}

void main()
{
	foo(1);
	foo([1,1]);

	auto tmp1 = new Data!(int);
	tmp1.elem = 3;
	foo(tmp1);

	auto tmp2 = new Data!(string);
	tmp2.elem = "hello";
	foo(tmp2);
}

void foo(T)(T t) if(!isArray!T)
{
	writeln(t + 1);
}

void foo(T)(T t) if(isArray!T)
{
	for(int i = 0; i < t.length; i++)
		writeln(t[i]);
}

void foo(T)(T t) if(is(T == Data)) // ?
{
	if(is(T == Data!int))
		writeln(t.elem + 1);
	else if(is(T == Data!string))
		writeln(t.elem);
}
--
December 12, 2012
On 12/12/2012 06:49 AM, Cube wrote:
> Better example code for my other problem. How can I make the 3rd foo
> work on Datas?
>
> --
> struct Data(T)
> {
> T elem;
> }

Data is a struct template, not a type (until instantiated).

> void foo(T)(T t) if(is(T == Data)) // ?

This works:

void foo(T)(T t) if(is(T == Data!T))

> {
> if(is(T == Data!int))
> writeln(t.elem + 1);
> else if(is(T == Data!string))
> writeln(t.elem);
> }
> --

Ali

December 12, 2012
On Wednesday, 12 December 2012 at 15:21:16 UTC, Ali Çehreli wrote:
> On 12/12/2012 06:49 AM, Cube wrote:
> > Better example code for my other problem. How can I make the
> 3rd foo
> > work on Datas?
> >
> > --
> > struct Data(T)
> > {
> > T elem;
> > }
>
> Data is a struct template, not a type (until instantiated).
>
> > void foo(T)(T t) if(is(T == Data)) // ?
>
> This works:
>
> void foo(T)(T t) if(is(T == Data!T))

It doesn't seem to work for me, it uses the first foo. And I can't see how it would work, actually.
If T is a Data!float, then wouldn't
is(T == Data!T)
be equal to
is(Data!float == Data!Data!float)
?

>
> Ali

December 12, 2012
Ali Çehreli:

> This works:
>
> void foo(T)(T t) if(is(T == Data!T))

Try:

void foo(T)(Data!T t) {

Bye,
bearophile
December 12, 2012
On Wednesday, 12 December 2012 at 14:21:22 UTC, bearophile wrote:
> ixid:
>
>> It's a pity it doesn't see T[] as the best fit and go with it on that basis.
>
> It's not a pity, it's a good design. "Best fit" makes language&compiler complex, less predictable for the programmer, etc.
>
> Bye,
> bearophile

It seems very similar to a function overload to me. Why is picking T[] in preference to T different to picking uint over ulong for an overloaded function used on a uint?
« First   ‹ Prev
1 2