cannot deduce function from argument types issue.
Hi! I get the following compile error (linux, dmd2.066.1): test.d(13): Error: template test.testFunc cannot deduce function from argument types !()(double[], double), candidates are: test.d(3):test.testFunc(R)(R range, ElementType!R foo) For the following test file: import std.range: ElementType, isInputRange; ElementType!R testFunc(R)( R range, ElementType!R foo) // compiles with double foo { static assert( isInputRange!R ); ElementType!R retVal = foo*foo; return retVal; } void main() { double[] values = [0.0, 3.0, -1.0, 5.0]; auto result = testFunc( values, 8.8 ); } And I'm not sure what I'm doing incorrectly. It compiles/works fine if I hardcode the type for foo. Could someone enlighten me ? regards, ted
Re: cannot deduce function from argument types issue.
Ali Çehreli wrote: On 02/10/2015 12:31 AM, ted wrote: ElementType!R testFunc(R)( R range, ElementType!R foo) // compiles with double foo If think it is a little too much to ask from the template system of D. A proper way of doing the same thing is to use a template constraint: ElementType!R testFunc(R, E)( R range, E foo) if (is (E : ElementType!R)) Ali thanks !
Re: cannot deduce function from argument types issue.
On 02/10/2015 12:31 AM, ted wrote: ElementType!R testFunc(R)( R range, ElementType!R foo) // compiles with double foo If think it is a little too much to ask from the template system of D. A proper way of doing the same thing is to use a template constraint: ElementType!R testFunc(R, E)( R range, E foo) if (is (E : ElementType!R)) Ali
Re: cannot deduce function from argument types issue.
ted: Could someone enlighten me ? This works: import std.range: ElementType, isInputRange; ElementType!R testFunc(R, T)(R range, T foo) if (is(ElementType!R == T)) { static assert(isInputRange!R); typeof(return) retVal = foo ^^ 2; // More DRY. return retVal; } void main() { auto values = [0.0, 3.0, -1.0, 5.0]; auto result = testFunc(values, 8.8); } The D compiler seems unable to compute ElementType!R in the function signature. If I am right, then this seems worth an enhancement request. Bye, bearophile
Re: cannot deduce function from argument types issue.
Ali Çehreli: If think it is a little too much to ask from the template system of D. I remember hitting a similar problem with code like this bar() function: // OK void foo(size_t N1, size_t N2)(int[N1] a, int[N2] b) if (N2 == N1 ^^ 2) {} // Not OK void bar(size_t N)(int[N] a, int[N ^ 2] b) {} void main() { int[2] a = [1, 2]; int[4] b = [1, 2, 3, 4]; foo(a, b); bar(a, b); } So perhaps my suggestion to file an enhancement request is not a good idea... Bye, bearophile
Re: cannot deduce function from argument types issue.
void bar(size_t N)(int[N] a, int[N ^ 2] b) {} I meant: void bar(size_t N)(int[N] a, int[N ^^ 2] b) {}
Re: cannot deduce function from argument types issue.
bearophile wrote: ted: Could someone enlighten me ? This works: import std.range: ElementType, isInputRange; ElementType!R testFunc(R, T)(R range, T foo) if (is(ElementType!R == T)) { static assert(isInputRange!R); typeof(return) retVal = foo ^^ 2; // More DRY. return retVal; } void main() { auto values = [0.0, 3.0, -1.0, 5.0]; auto result = testFunc(values, 8.8); } The D compiler seems unable to compute ElementType!R in the function signature. If I am right, then this seems worth an enhancement request. Bye, bearophile thanks !... ... where you say 'More DRY' above, are you referring to - foo^^2 ( I just did foo*foo for the sake of the example), or - typeof(return) - a construct I am completely unfamiliar with and will now have to look up ! If it is 'typeof(return)' why would this be selected over ElementType!R ?? Is it more idiomatic ? regards, ted
Re: cannot deduce function from argument types issue.
bearophile wrote: ted: ... where you say 'More DRY' above, are you referring to I was referring to both, but mostly to the typeof. It's more DRY (http://en.wikipedia.org/wiki/Don%27t_repeat_yourself ). You are stating only once the type of the return variable. This is less bug-prone. Bye, bearophile Ha ! ..more stuff to learn! many thanks... regards, ted
Re: cannot deduce function from argument types issue.
ted: ... where you say 'More DRY' above, are you referring to I was referring to both, but mostly to the typeof. It's more DRY (http://en.wikipedia.org/wiki/Don%27t_repeat_yourself ). You are stating only once the type of the return variable. This is less bug-prone. Bye, bearophile
Re: cannot deduce function from argument types issue.
On 02/10/2015 01:08 AM, bearophile wrote: // Not OK void bar(size_t N)(int[N] a, int[N ^^ 2] b) {} So perhaps my suggestion to file an enhancement request is not a good idea... I am not sure. Although the template system already does pretty clever deductions, I think they are all based on hints given by the programmer. They work forward from the rules. However, both in your example above and in ted's code, the compiler has to solve a problem similar to declarative programming languages to arrive at the intent. For example, it must apply sqrt to the second length to figure out N. Admittedly, it is not apparent in the code above because the first parameter is already trivially N so the human reader thinks N comes from the first argument and it must also satisfy the second argument. The following would ask the compiler to work backward from the argument: void bar(size_t N)(int[N ^^ 2] b) {} Take a value from the argument, take its square root and then use that value to figure out the instantiation value of this template. Ali