www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Deducing a template retrun parameter type based on an assignment?

reply "Jeremy DeHaan" <dehaan.jeremiah gmail.com> writes:
I have a template fuction that looks like this:

immutable(T)[] getString(T)() const
if (is(T == dchar)||is(T == wchar)||is(T == char))

Basically, I was hoping that the type would be deduced based on 
the prameter that was being assigned to like so.

string ret = thing.getString();

Apparently that does not work, though. I get informed that the 
type of the template is not able to be deduced. I'm curious as to 
why it was not able to deduce it on its own.

Additionally, and I haven't run my code to try this yet, but 
giving T a default type compiled to my surprise.

immutable(T)[] getString(T=char)() const
if (is(T == dchar)||is(T == wchar)||is(T == char))

Is something like this supposed even to work?
Jan 29 2015
parent reply "Vlad Levenfeld" <vlevenfeld gmail.com> writes:
On Friday, 30 January 2015 at 06:35:31 UTC, Jeremy DeHaan wrote:
 I have a template fuction that looks like this:

 immutable(T)[] getString(T)() const
 if (is(T == dchar)||is(T == wchar)||is(T == char))

 Basically, I was hoping that the type would be deduced based on 
 the prameter that was being assigned to like so.

 string ret = thing.getString();

 Apparently that does not work, though. I get informed that the 
 type of the template is not able to be deduced. I'm curious as 
 to why it was not able to deduce it on its own.

 Additionally, and I haven't run my code to try this yet, but 
 giving T a default type compiled to my surprise.

 immutable(T)[] getString(T=char)() const
 if (is(T == dchar)||is(T == wchar)||is(T == char))

 Is something like this supposed even to work?
for template type deduction to work, you have to supply an argument. Your type signature would need to look like this: immutable(T)[] getString(T)(T arg) const and then T would be deduced from arg. But string ret = thing.getString(); won't compile because it is rewritten to getString(thing), but your getString function takes no runtime parameters. It looks like the signature I wrote earlier is what you actually want. As to your second example, it'll work fine. Basically your signature says "only accept dchar, wchar or char, but if nothing's been specified, default to char". But if you rewrite getString to take one parameter, then the default template arg is redundant.
Jan 29 2015
parent reply "Jeremy DeHaan" <Dehaan.jeremiah gmail.com> writes:
On Friday, 30 January 2015 at 06:58:58 UTC, Vlad Levenfeld wrote:
 On Friday, 30 January 2015 at 06:35:31 UTC, Jeremy DeHaan wrote:
A bunch of stuff
for template type deduction to work, you have to supply an argument. Your type signature would need to look like this: immutable(T)[] getString(T)(T arg) const and then T would be deduced from arg.
That seems strange. I figured that it would be smart enough to deduce the parameter type based on the type that it was trying to be assigned to.
 But string ret = thing.getString(); won't compile because it is 
 rewritten to getString(thing), but your getString function 
 takes no runtime parameters. It looks like the signature I 
 wrote earlier is what you actually want.
Whoops. I should have mentioned that this is a member function in a class and not a free fiction. Not that it changes much about the deduction.
 As to your second example, it'll work fine. Basically your 
 signature says "only accept dchar, wchar or char, but if 
 nothing's been specified, default to char". But if you rewrite 
 getString to take one parameter, then the default template arg 
 is redundant.
That is good to hear. It seemed like that was the way it would work, but I've never had to specify a default template parameter type. I'm hoping to avoid having to specify a template parameter, but it seems like it can't be helped if users want to get their string type as a wstring or dstring though.
Jan 29 2015
next sibling parent "Vlad Levenfeld" <vlevenfeld gmail.com> writes:
On Friday, 30 January 2015 at 07:13:09 UTC, Jeremy DeHaan wrote:
 That seems strange. I figured that it would be smart enough to
 deduce the parameter type based on the type that it was trying 
 to
 be assigned to.
It seems sensible to me, as changing string to auto would leave the type of the expression undefined. But maybe your expectation is a reasonable enhancement, I'll leave it for someone more knowledgeable than myself to judge.
 That is good to hear. It seemed like that was the way it would
 work, but I've never had to specify a default template parameter
 type. I'm hoping to avoid having to specify a template 
 parameter,
 but it seems like it can't be helped if users want to get their
 string type as a wstring or dstring though.
It doesn't seem too bad to me. I used a similar pattern quite recently to wrap glGetIntegeriv into gl.get!int. One way or another you'll have to specify the type, but if you want to cut down on redundant code then auto ret = thing.getString!wchar; is a good bet. And I'm fairly certain that since you're using a default param of char, auto ret = thing.getString; should compile and result in ret being a char string.
Jan 29 2015
prev sibling parent reply "bearophile" <bearophileHUGS lycos.com> writes:
Jeremy DeHaan:

 I figured that it would be smart enough to
 deduce the parameter type based on the type that it was trying 
 to be assigned to.
For that you need languages like Haskell/Rust. D type inference doesn't work from the type something is assigned to. Bye, bearophile
Jan 30 2015
parent reply "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net> writes:
On Friday, 30 January 2015 at 08:52:41 UTC, bearophile wrote:
 Jeremy DeHaan:

 I figured that it would be smart enough to
 deduce the parameter type based on the type that it was trying 
 to be assigned to.
For that you need languages like Haskell/Rust. D type inference doesn't work from the type something is assigned to.
But it could, right (for arguments and return expressions, too)? At least I don't see any real obstacles. Just file an enhancement request if you think it's worthwhile, or start a discussion on digitalmars.D. Of course, it cannot work for `auto x = getString();` or `foo(getString())` where there are several overloads of `foo()`. The next step would then be overloading on the return type, which is related.
Jan 30 2015
parent Steven Schveighoffer <schveiguy yahoo.com> writes:
On 1/30/15 5:06 AM, "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net>" 
wrote:
 On Friday, 30 January 2015 at 08:52:41 UTC, bearophile wrote:
 Jeremy DeHaan:

 I figured that it would be smart enough to
 deduce the parameter type based on the type that it was trying to be
 assigned to.
For that you need languages like Haskell/Rust. D type inference doesn't work from the type something is assigned to.
But it could, right (for arguments and return expressions, too)? At least I don't see any real obstacles. Just file an enhancement request if you think it's worthwhile, or start a discussion on digitalmars.D. Of course, it cannot work for `auto x = getString();` or `foo(getString())` where there are several overloads of `foo()`. The next step would then be overloading on the return type, which is related.
Walter made a conscious decision not to depend on return types for overloads or any other deduction. It makes implementation of the language simpler. C++ has tremendously complex rules for overloading because of this. Note, you can easily change this: string x = getString(); to this: auto x = getString!(char)(); which is still DRY. One possible mechanism for working around this for when you already have a variable is to change the return value into a parameter void getStringParam(T)(ref T[] x) if ... { x = getString!(T)(); } -Steve
Jan 30 2015