www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - how to get rid of "cannot deduce function from argument types"

reply =?UTF-8?Q?Christian_K=c3=b6stlin?= <christian.koestlin gmail.com> writes:
I made a small (could be reduced further) example that creates and walks
a templated binary tree. The tree also gets a factory function to use
type deduction to conveniently construct a tree. Unfortunately this does
not compile, if I remove the three ugly methods between /* these should
go */ comments.

```
fibertest.d(49): Error: template fibertest.tree cannot deduce function
from argument types !()(int, typeof(null), typeof(null)), candidates are:
fibertest.d(41):        fibertest.tree(T)(T node, Tree!T left, Tree!T right)
```

Is there a more elegant way to fix this?

Another fix would be to provide 4 factory functions like this (still not
really nice):
```
tree(Tree!T left, T node, Tree!T right) {...}
tree(T node, Tree!T right) {...}
tree(Tree!T left, T node) {...}
tree(T node) {...}
```

```d
import std.concurrency, std.stdio, std.range;

class Tree(T) {
  Tree!T left;
  T node;
  Tree!T right;

  this(Tree!T left, T node, Tree!T right) {
    this.left = left;
    this.node = node;
    this.right = right;
  }

  auto inorder() {
    return new Generator!T(() => yieldAll(this));
  }

  private void yieldAll(Tree!T t) {
    if (t is null) return;

    yieldAll(t.left);
    yield(t.node);
    yieldAll(t.right);
  }
}

/* these should go */

Tree!T tree(T)(typeof(null) left, T node, typeof(null) right) {
  return new Tree!T(null, node, null);
}
Tree!T tree(T)(Tree!T left, T node, typeof(null) right) {
  return new Tree!T(left, node, null);
}
Tree!T tree(T)(typeof(null) left, T node, Tree!T right) {
  return new Tree!T(null, node, right);
}

/* these should go */

Tree!T tree(T)(Tree!T left, T node, Tree!T right) {
  return new Tree!T(left, node, right);
}

void main(string[] args) {
  //     /3
  //   /2
  //  1
  auto t1 = tree(tree(tree(null, 1, null), 2, null), 3, null);
  // 1
  //  \2
  //    \3
  auto t2 = tree(null, 1, tree(null, 2, tree(null, 3, null)));
  writeln(t1.inorder());
  writeln(t2.inorder());
  writeln(t1.inorder().array == t2.inorder().array);
}
```
Jun 13 2016
parent reply =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 06/13/2016 03:30 PM, Christian Köstlin wrote:

 Tree!T tree(T)(Tree!T left, T node, Tree!T right) {
   return new Tree!T(left, node, right);
 }
This works but I don't know whether it's a bug or not: Tree!T tree(TT, T)(TT left, T node, TT right) { return new Tree!T(left, node, right); } Perhaps this is better: Tree!T tree(TL, T, TR)(TL left, T node, TR right) { return new Tree!T(left, node, right); } Ali
Jun 13 2016
parent reply pineapple <meapineapple gmail.com> writes:
On Monday, 13 June 2016 at 22:54:13 UTC, Ali Çehreli wrote:
 Tree!T tree(TL, T, TR)(TL left, T node, TR right) {
   return new Tree!T(left, node, right);
 }
There's also this: Tree!T tree(TL, T, TR)(TL left, T node, TR right) if( (is(TL == Tree!T) || is(TL == typeof(null))) && (is(TR == Tree!T) || is(TR == typeof(null))) ){ return new Tree!T(left, node, right); }
Jun 14 2016
parent Steven Schveighoffer <schveiguy yahoo.com> writes:
On 6/14/16 6:05 AM, pineapple wrote:
 On Monday, 13 June 2016 at 22:54:13 UTC, Ali Çehreli wrote:
 Tree!T tree(TL, T, TR)(TL left, T node, TR right) {
   return new Tree!T(left, node, right);
 }
There's also this: Tree!T tree(TL, T, TR)(TL left, T node, TR right) if( (is(TL == Tree!T) || is(TL == typeof(null))) && (is(TR == Tree!T) || is(TR == typeof(null)))
Alternative: if(is(typeof({Tree!T x = TL.init; x = TR.init; }))) This may seem similar, but actually can accept things that convert to Tree!T as well. The issue with the OP code is that the compiler is trying to match T with the two null parameters, and can't work out the deduction. -Steve
Jun 14 2016