Thread overview | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
|
April 19, 2014 Template method and type resolution of return type | ||||
---|---|---|---|---|
| ||||
Hi everyone ! Let's say I have a struct : struct Test { immutable (ubyte)[] data; T get(T)() { return *(cast(T*)(&(data[0]))); } } This code will work : import std.stdio; void main() { Test t; t.data = [152, 32, 64, 28, 95]; float b = t.get!float; writefln("%s", b); } This won't compile : import std.stdio; void main() { Test t; t.data = [152, 32, 64, 28, 95]; float b = t.get; writefln("%s", b); } This neither: import std.stdio; void main() { Test t; t.data = [152, 32, 64, 28, 95]; float b = t.get!(typeof(b)); writefln("%s", b); } And this will work: import std.stdio; void main() { Test t; t.data = [152, 32, 64, 28, 95]; float b; b = t.get!(typeof(b)); writefln("%s", b); } Why can't dmd infere the type 'float' ? In fact this would allow a nicer syntax for the Json struct in vibe.d for example. |
April 19, 2014 Re: Template method and type resolution of return type | ||||
---|---|---|---|---|
| ||||
Posted in reply to matovitch | matovitch: > struct Test > { > immutable (ubyte)[] data; > > T get(T)() > { > return *(cast(T*)(&(data[0]))); > } It's better to return const/immutable data. Otherwise the program gives undefined results. In alternative use mutable ubytes for data. Also &data[0] is probably data.ptr. > This won't compile : > > import std.stdio; > > void main() > { > Test t; > t.data = [152, 32, 64, 28, 95]; > float b = t.get; > writefln("%s", b); D doesn't perform inference on the return type. > This neither: >... > Test t; > t.data = [152, 32, 64, 28, 95]; > float b = t.get!(typeof(b)); > writefln("%s", b); I don't know. Perhaps b is not yet defined. This in theory could work. > In fact this would allow a nicer syntax for the Json struct in vibe.d for example. I don't think in future D will behave differently on this code. Bye, bearophile |
April 19, 2014 Re: Template method and type resolution of return type | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | On Saturday, 19 April 2014 at 17:49:54 UTC, bearophile wrote: > matovitch: > >> struct Test >> { >> immutable (ubyte)[] data; >> >> T get(T)() >> { >> return *(cast(T*)(&(data[0]))); >> } > > It's better to return const/immutable data. Otherwise the program gives undefined results. In alternative use mutable ubytes for data. > > Also &data[0] is probably data.ptr. I did'nt know that one. > > >> This won't compile : >> >> import std.stdio; >> >> void main() >> { >> Test t; >> t.data = [152, 32, 64, 28, 95]; >> float b = t.get; >> writefln("%s", b); > > D doesn't perform inference on the return type. I see. But why ? It's seems it exits a workaround overloading cast operators in c++ : http://programmaticallyspeaking.blogspot.se/2012/09/infer-return-type-for-templated.html However I think it would only work with opImplicitCast in D. The code given in vibe.d doc could became : void manipulateJson(Json j) { j = Json.emptyObject; j.name = "Example"; j.id = 1; // retrieving the values is done using get() assert(j["name"] == "Example"); assert(j["id"] == 1); // print out as JSON: {"name": "Example", "id": 1} writefln("JSON: %s", j.toString()); } ps : Thank you for all your great examples on Rosetta code (or the last one about the rubik's cube). |
April 19, 2014 Re: Template method and type resolution of return type | ||||
---|---|---|---|---|
| ||||
Posted in reply to matovitch | On Saturday, 19 April 2014 at 18:46:28 UTC, matovitch wrote: > On Saturday, 19 April 2014 at 17:49:54 UTC, bearophile wrote: >> matovitch: > > I did'nt know that one. > This last sentence is misleading, let be clear : I know almost nothing when it comes to D...but I'm willing to learn ! ;-) |
April 19, 2014 Re: Template method and type resolution of return type | ||||
---|---|---|---|---|
| ||||
Posted in reply to matovitch | On Saturday, 19 April 2014 at 18:46:28 UTC, matovitch wrote:
> On Saturday, 19 April 2014 at 17:49:54 UTC, bearophile wrote:
>> matovitch:
>>
>>> struct Test
>>> {
>>> immutable (ubyte)[] data;
>>>
>>> T get(T)()
>>> {
>>> return *(cast(T*)(&(data[0])));
>>> }
>>
>> It's better to return const/immutable data. Otherwise the program gives undefined results. In alternative use mutable ubytes for data.
>>
>> Also &data[0] is probably data.ptr.
>
> I did'nt know that one.
>
>>
>>
>>> This won't compile :
>>>
>>> import std.stdio;
>>>
>>> void main()
>>> {
>>> Test t;
>>> t.data = [152, 32, 64, 28, 95];
>>> float b = t.get;
>>> writefln("%s", b);
>>
>> D doesn't perform inference on the return type.
>
> I see. But why ?
>
> It's seems it exits a workaround overloading cast operators in c++ :
> http://programmaticallyspeaking.blogspot.se/2012/09/infer-return-type-for-templated.html
>
> However I think it would only work with opImplicitCast in D. The code given in vibe.d doc could became :
>
> void manipulateJson(Json j)
> {
> j = Json.emptyObject;
> j.name = "Example";
> j.id = 1;
>
> // retrieving the values is done using get()
> assert(j["name"] == "Example");
> assert(j["id"] == 1);
>
> // print out as JSON: {"name": "Example", "id": 1}
> writefln("JSON: %s", j.toString());
> }
>
>
> ps : Thank you for all your great examples on Rosetta code (or the last one about the rubik's cube).
Or even :
void manipulateJson(Json j)
{
j = Json.emptyObject;
j.name = "Example";
j.id = 1;
assert(j.name == "Example");
assert(j.id == 1);
// print out as JSON: {"name": "Example", "id": 1}
writefln("JSON: %s", j.toString());
}
Or at least this will work :
void manipulateJson(Json j)
{
j = Json.emptyObject;
j.name = "Example";
j.id = 1;
string s = j.name;
assert(s == "Example");
// print out as JSON: {"name": "Example", "id": 1}
writefln("JSON: %s", j.toString());
}
Ok I stop fooding.
|
April 19, 2014 Re: Template method and type resolution of return type | ||||
---|---|---|---|---|
| ||||
Posted in reply to matovitch | On 4/19/14, matovitch via Digitalmars-d-learn <digitalmars-d-learn@puremagic.com> wrote: > This won't compile : > > import std.stdio; > > void main() > { > Test t; > t.data = [152, 32, 64, 28, 95]; > float b = t.get; > writefln("%s", b); > } Because it's probably overkill. At some point it becomes too much magic. The following currently works but it might be considered an ambiguity with return type inference: ----- struct S { int get() { return 0; } T get(T)() { return T.init; } } void main() { S s; float x = s.get(); // which overload? (currently int get()) } ----- |
April 20, 2014 Re: Template method and type resolution of return type | ||||
---|---|---|---|---|
| ||||
Posted in reply to Andrej Mitrovic | On 4/19/2014 3:31 PM, Andrej Mitrovic via Digitalmars-d-learn wrote:
> [...]
> struct S
> {
> int get() { return 0; }
> T get(T)() { return T.init; }
> }
>
> void main()
> {
> S s;
> float x = s.get(); // which overload? (currently int get())
> }
Isn't this just because concrete methods are better overload candidates than method templates?
Dave
|
April 20, 2014 Re: Template method and type resolution of return type | ||||
---|---|---|---|---|
| ||||
Posted in reply to David Held | On Sunday, 20 April 2014 at 00:55:31 UTC, David Held wrote:
> On 4/19/2014 3:31 PM, Andrej Mitrovic via Digitalmars-d-learn wrote:
>> [...]
>> struct S
>> {
>> int get() { return 0; }
>> T get(T)() { return T.init; }
>> }
>>
>> void main()
>> {
>> S s;
>> float x = s.get(); // which overload? (currently int get())
>> }
>
> Isn't this just because concrete methods are better overload candidates than method templates?
>
> Dave
struct S
{
ubyte get() { return 0 ; }
float get() { return 0.; }
}
void main()
{
S s;
float x = s.get(); // does'nt know which overload, does'nt compile.
}
|
April 20, 2014 Re: Template method and type resolution of return type | ||||
---|---|---|---|---|
| ||||
Posted in reply to matovitch | On Sunday, 20 April 2014 at 07:52:08 UTC, matovitch wrote:
>
> struct S
> {
> ubyte get() { return 0 ; }
> float get() { return 0.; }
> }
>
> void main()
> {
> S s;
> float x = s.get(); // does'nt know which overload, does'nt compile.
> }
What I do find interesting though, is that you are allowed to write the overload, whereas C++ would outright block you for ambiguity "at the source".
This means that with proper meta magic eg `__traits(getOverloadSet, S, "get")`, you could, *manually* resolve the ambiguity yourself.
|
April 20, 2014 Re: Template method and type resolution of return type | ||||
---|---|---|---|---|
| ||||
Posted in reply to monarch_dodra | On Sunday, 20 April 2014 at 08:28:07 UTC, monarch_dodra wrote:
> On Sunday, 20 April 2014 at 07:52:08 UTC, matovitch wrote:
>>
>> struct S
>> {
>> ubyte get() { return 0 ; }
>> float get() { return 0.; }
>> }
>>
>> void main()
>> {
>> S s;
>> float x = s.get(); // does'nt know which overload, does'nt compile.
>> }
>
> What I do find interesting though, is that you are allowed to write the overload, whereas C++ would outright block you for ambiguity "at the source".
>
> This means that with proper meta magic eg `__traits(getOverloadSet, S, "get")`, you could, *manually* resolve the ambiguity yourself.
You mean getOverloads ? (yes it's interesting)
How about this :
class S
{
public
{
this() {}
union other {
SFloat u_float;
SUbyte u_ubyte;
}
alias other this;
}
}
struct SFloat
{
float data;
alias data this;
}
struct SUbyte
{
ubyte data;
alias data this;
}
void main()
{
S s;
s.other.u_float.data = 0.5;
//float x = s;
}
This gives :
main.d(31): Error: need 'this' for 'data' of type 'float'
|
Copyright © 1999-2021 by the D Language Foundation