digitalmars.D.learn - Templates array detection
- Cube (21/21) Dec 12 2012 Hi,
- bearophile (21/41) Dec 12 2012 In general D templates refuse ambiguity. So to fix your situation
- Cube (55/100) Dec 12 2012 Hi,
- Cube (35/35) Dec 12 2012 Better example code for my other problem. How can I make the 3rd
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (5/20) Dec 12 2012 This works:
- Cube (8/23) Dec 12 2012 It doesn't seem to work for me, it uses the first foo. And I
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (46/72) Dec 12 2012 I have to deal with the magical 'is expression' again! :p
- bearophile (5/7) Dec 12 2012 Try:
- ixid (3/48) Dec 12 2012 It's a pity it doesn't see T[] as the best fit and go with it on
- bearophile (6/8) Dec 12 2012 It's not a pity, it's a good design. "Best fit" makes
- ixid (4/12) Dec 12 2012 It seems very similar to a function overload to me. Why is
- bearophile (9/12) Dec 12 2012 The name T can refer to any type, including a U[], while built-in
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]); } --
Dec 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
Dec 12 2012
On Wednesday, 12 December 2012 at 12:34:34 UTC, bearophile wrote:Cube: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 :)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
Dec 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); } --
Dec 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
Dec 12 2012
On Wednesday, 12 December 2012 at 15:21:16 UTC, Ali Çehreli wrote:On 12/12/2012 06:49 AM, Cube wrote: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) ?Better example code for my other problem. How can I make the3rd foowork 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))Ali
Dec 12 2012
On 12/12/2012 07:37 AM, Cube wrote:On Wednesday, 12 December 2012 at 15:21:16 UTC, Ali Çehreli wrote:I have to deal with the magical 'is expression' again! :p First, also notice that you ar not passing Data!T but a pointer to Data!T. This program works: import std.stdio; import std.traits; 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 && !is(T ThisIsNeededButUnusable : Data!U*, U)) { 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 ThisIsNeededButUnusable : Data!U*, U)) { writeln("desired"); // Note that both of the 'if's are replaced with 'static if's. // Also, both are 'pointers' in the conditionals. static if(is(T == Data!int*)) writeln(t.elem + 1); else static if(is(T == Data!string*)) writeln(t.elem); } I think ThisIsNeededButUnusable above is a compiler bug. It has a use when the body of the 'is' is used inside template parameter lists but not in a template constraint. It is still needed to satisfy the syntax... (?) AliOn 12/12/2012 06:49 AM, Cube wrote: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) ?Better example code for my other problem. How can I make the3rd foowork 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))
Dec 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
Dec 12 2012
On Wednesday, 12 December 2012 at 12:34:34 UTC, bearophile wrote:Cube:It's a pity it doesn't see T[] as the best fit and go with it on that basis.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
Dec 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
Dec 12 2012
On Wednesday, 12 December 2012 at 14:21:22 UTC, bearophile wrote:ixid: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?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
Dec 12 2012
ixid: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?The name T can refer to any type, including a U[], while built-in types like uint are atomic, they can't refer to a composed type. And there is difference between a built-in type where both the programmer and the compiler know about, and generic user defined types. And template types are used in an exact way, unlike function overloading they don't perform implicit type conversions. Bye, bearophile
Dec 12 2012