digitalmars.D.learn - "cannot deduce function from argument types" issue.
- ted (25/25) Feb 10 2015 Hi!
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (6/8) Feb 10 2015 If think it is a little too much to ask from the template system of D. A...
- bearophile (18/20) Feb 10 2015 I remember hitting a similar problem with code like this bar()
- bearophile (2/3) Feb 10 2015 I meant:
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (16/20) Feb 10 2015 I am not sure. Although the template system already does pretty clever
- ted (3/15) Feb 10 2015 ....thanks !
- bearophile (18/19) Feb 10 2015 This works:
- ted (10/38) Feb 10 2015 thanks !...
- bearophile (7/8) Feb 10 2015 I was referring to both, but mostly to the typeof. It's more DRY
- ted (6/17) Feb 10 2015 Ha !
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
Feb 10 2015
On 02/10/2015 12:31 AM, ted wrote:ElementType!R testFunc(R)( R range, ElementType!R foo) // compiles with double fooIf 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
Feb 10 2015
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
Feb 10 2015
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) {}
Feb 10 2015
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
Feb 10 2015
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 !
Feb 10 2015
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
Feb 10 2015
bearophile wrote:ted: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, tedCould 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
Feb 10 2015
ted:... where you say 'More DRY' above, are you referring toI 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
Feb 10 2015
bearophile wrote:ted:Ha ! ..more stuff to learn! many thanks... regards, ted... where you say 'More DRY' above, are you referring toI 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
Feb 10 2015