On Friday, 16 October 2015 at 15:48:59 UTC, Edwin van Leeuwen
wrote:
Just wondering if anyone has any tips on how to solve/avoid
"cannot deduce function from argument types" when relying on
template programming.
I run into these problems all the time. Current one was when I
tried:
```
auto ys = NumericLabel(groupedAes.front.map!((t)=>t.y));
```
NumericLabel is a pretty minimal templated InputRange, with as
only requirement on the argument that it is also an InputRange.
I then get the following compile error:
```
source/ggplotd/geom.d(83,35): Error: struct
ggplotd.aes.NumericLabel cannot ded
uce function from argument types !()(MapResult!(__lambda2,
FilterResult!(__lamb
da2, Aes!(double[], "x", double[], "y", string[], "colour")))),
candidates are:
source/ggplotd/aes.d(515,1): ggplotd.aes.NumericLabel(T)
if (isInputRang
e!T)
```
As far as I know MapResult always returns an input range and as
you can see there is only one candidate of NumericLabel, so to
be honest it looks relatively straightforward to me.
Without seeing more code I can't be 100% sure, but I think it's
just that you're expecting explicit function template
instantiation (IFTI) for work for constructors, but it doesn't.
you have to explicitly provide the template arguments or use a
free function that forwards to the constructor.
Now I can define the type specifically (and/or typeof) but it
seems like there should be a better way.
In this case typeof isn't even happy:
```
source/ggplotd/geom.d(84,17): Error: constructor
ggplotd.aes.NumericLabel!(MapResult!(__lambda2,
FilterResult!(__lambda2, Aes!(string[], "x", string[], "y",
string[], "colour")))).NumericLabel.this (MapResult!(__lambda2,
FilterResult!(__lambda2, Aes!(string[], "x", string[], "y",
string[], "colour"))) range) is not callable using argument
types (MapResult!(__lambda3, FilterResult!(__lambda2,
Aes!(string[], "x", string[], "y", string[], "colour"))))
```
If we look closely, it expects a __lambda2 as the MapResult
argument, but it gets a __lambda3.
I am able to work around it by converting the mapresult to an
array, but I'd rather use a lazy solution.
Sadly lambdas aren't currently comparable for equality. Maybe on
day...
If you use the string lambda "a.y" it will probably work.
The more general workaround is to create a temporary variable and
then use typeof on that, then use that temporary variable.
The idiomatic solution in this case though is to use a function
as mentioned above.