Re: template this and traits getOverloads issue.

2015-11-20 Thread Alex Parrill via Digitalmars-d-learn
Alternatively, you can use a static method and pass in the 
instance.


Note that `new B` will print A's members twice, because A's 
constructor is always called and `__traits(allMembers, B)` 
includes A's members.


---

import std.stdio;

mixin template Bug()
{
import std.traits;
static void bug(T)(T t)
{
writeln(">", T.stringof);
foreach(member; __traits(allMembers, T))
foreach(overload; __traits(getOverloads, T, member))
{
auto dg = 
writeln(member);
}
}
}

class A
{
mixin Bug;
this(){bug!A(this);}
void foo(){}
}

class B: A
{
this(){bug!B(this);}
void bar(){}
void bar(uint a){}
}

void main(){
new A;
new B;
}


Re: template this and traits getOverloads issue.

2015-11-20 Thread BBasile via Digitalmars-d-learn

On Friday, 20 November 2015 at 14:18:00 UTC, Alex Parrill wrote:

If the mixin has to be used on class and on struct, I cant use an 
interface. In this case override will create an error and go back 
to the solution on SO: statically check if things are already 
there.


Templates are not virtual, which is why you might be running 
into issues here; bug thinks it's being called on an `A` object.


This is the origin of the problem, I totally forgot this 
limitation.





Re: template this and traits getOverloads issue.

2015-11-20 Thread Adam D. Ruppe via Digitalmars-d-learn

On Friday, 20 November 2015 at 14:18:00 UTC, Alex Parrill wrote:
But you don't need a template for this case; mixin templates 
have access to `this`:


Indeed, this is a good answer too.

The difference between this and the template thing I did is that 
yours is virtual so calling it through an interface will work 
even on subclasses. However, you must mix it into each sub class.


Mine is a template that only needs to be in the base 
class/interface, but also need a `this` of the derived type to 
see the derived type. (That's why I ran `this.bug();` in the 
constructor of B btw) If you call it on an variable typed as the 
interface, it will only show interface members.


IF i = new A();
i.bug(); // would only show interface members with mine

A a = new A();
a.bug(); // will now show A's members too

That's what the template this parameter does: the type of this at 
the *usage site* is passed as the parameter.



With your solution, the type of this at the *mixin site* is 
available.




I think your solution is generally better for stuff like 
serialization where you are passed an interface but need child 
members too. The template this param I used is nice for interface 
functions that need some kind of covariance; returning a type 
based on how it was used.


Re: template this and traits getOverloads issue.

2015-11-20 Thread Adam D. Ruppe via Digitalmars-d-learn

On Friday, 20 November 2015 at 14:01:13 UTC, BBasile wrote:
everything that can be done to avoid the compilations errors 
will also prevent "bar" to be written in the output (because a 
B will never be analyzed). The "only" fix I see is like in the 
stack overflow answer: statically check if the mixin methods 
are already there and remix the mixin in each descendant, so 
that the getOverloads traits works on the right 'this'.


Did you try using a template this parameter like I said in my 
comment?


import std.stdio;

mixin template Bug()
{
import std.traits;
void bug(this T)()
{
T this_ = cast(T) this;
foreach(member; __traits(allMembers, T))
foreach(idx, overload; __traits(getOverloads, T, 
member))

{
auto dg = &(__traits(getOverloads, this_, 
member)[idx]);
writeln(T.stringof, ".", member, " ", 
typeof(dg).stringof);

}
}
}

class A
{
mixin Bug;
this(){bug;}
void foo(){}
}

class B: A
{
void bar(){}
void bar(uint a){}
this(){this.bug;}
}

void main(){
new A;
new B;
}




There's a couple quirks in there, but I think you'll find the 
output shows what you want to see.


Re: template this and traits getOverloads issue.

2015-11-20 Thread Alex Parrill via Digitalmars-d-learn

On Friday, 20 November 2015 at 14:01:13 UTC, BBasile wrote:

Background:
===

http://stackoverflow.com/questions/33764540/warning-about-overriden-methods-when-using-a-mixin

Why this horrible trick has to be used:
===

cast this as (T) in a function template that's been mixed in an 
ancestor is not always usable, unless I miss something:



import std.stdio;

mixin template Bug()
{
import std.traits;
void bug(T)()
{
foreach(member; __traits(allMembers, T))
foreach(overload; __traits(getOverloads, T, member))
{
auto dg = 
writeln(member);
}
}
}

class A
{
mixin Bug;
this(){bug!A;}
void foo(){}
}

class B: A
{
void bar(){}
void bar(uint a){}
this(){bug!B;}
}

void main(){
new A;
new B;
}




a.d(11,27): Error: this for bar needs to be type B not type a.A
a.d(11,27): Error: this for bar needs to be type B not type a.A
a.d(11,27): Error: this for this needs to be type B not type a.A



everything that can be done to avoid the compilations errors 
will also prevent "bar" to be written in the output (because a 
B will never be analyzed). The "only" fix I see is like in the 
stack overflow answer: statically check if the mixin methods 
are already there and remix the mixin in each descendant, so 
that the getOverloads traits works on the right 'this'.


What do you think ? is it a bug ?


Templates are not virtual, which is why you might be running into 
issues here; bug thinks it's being called on an `A` object.


But you don't need a template for this case; mixin templates have 
access to `this`:


---
import std.stdio;

mixin template Bug()
{
import std.traits;
override void bug()
{
foreach(member; __traits(allMembers, typeof(this)))
foreach(overload; __traits(getOverloads, 
typeof(this), member))

{
auto dg = 
writeln(member);
}
}
}

// Interface to allow for mixin template to use `override` 
without worrying if

// `bug` is the first implementation or not.
interface IF {
void bug();
}

class A : IF
{
mixin Bug;
this(){bug();}
void foo(){}
}

class B: A
{
mixin Bug; // need mixin on B now to override `bug` for the 
new class

void bar(){}
void bar(uint a){}
}

void main(){
new A;
new B;
}


Re: template this and traits getOverloads issue.

2015-11-20 Thread BBasile via Digitalmars-d-learn

On Friday, 20 November 2015 at 14:39:29 UTC, Alex Parrill wrote:
Alternatively, you can use a static method and pass in the 
instance.


Initially this solution looked awesome but when `bug()` is 
static, `` returns some functions, not some delegates, which 
is a problem: this implies that I have to find the matching 
delegate type, set `.funcptr` to the value of the `dg` function, 
set `.ptr` to the value of 't'...well not so hard I guess.


But then I have no way to detect when a function is really a 
function or something that might be delegate when instantiated:



{
auto dg = 
if (member == "bar")
writeln(member, " ", typeof(dg).stringof);
}

--> bar void function()
--> bar void function(uint a)


Note that `new B` will print A's members twice, because A's 
constructor is always called and `__traits(allMembers, B)` 
includes A's members.


Not a problem, it was already the case anyway.

But thx much for the attempt.





Re: template this and traits getOverloads issue.

2015-11-20 Thread BBasile via Digitalmars-d-learn

On Friday, 20 November 2015 at 14:49:28 UTC, Adam D. Ruppe wrote:

On Friday, 20 November 2015 at 14:01:13 UTC, BBasile wrote:
everything that can be done to avoid the compilations errors 
will also prevent "bar" to be written in the output (because a 
B will never be analyzed). The "only" fix I see is like in the 
stack overflow answer: statically check if the mixin methods 
are already there and remix the mixin in each descendant, so 
that the getOverloads traits works on the right 'this'.


Did you try using a template this parameter like I said in my 
comment?


foreach(idx, overload; __traits(getOverloads, T, 
member))

{
auto dg = &(__traits(getOverloads, this_, 
member)[idx]);



Yes, using an index and a second call to getOverloads works, 
"finally".

No need to remix. Thx. I hadn't understood what you meant on SO.

One last question: is it possible to nest the calls to functions 
that take this kind of parameters ?


mixin template Bug()
{
 void bug0(this T)(){}
 void bug1(this T)(){}
 void allbugs(this T)(){this.bug0(); this.bug1();}
}

I've tried different parameters and templates and it never works.


Re: template this and traits getOverloads issue.

2015-11-20 Thread Adam D. Ruppe via Digitalmars-d-learn

On Friday, 20 November 2015 at 15:43:00 UTC, BBasile wrote:
One last question: is it possible to nest the calls to 
functions that take this kind of parameters ?


auto this_ = cast(T) this;
this_.bug0();
this_.bug1();


Re: template this and traits getOverloads issue.

2015-11-20 Thread BBasile via Digitalmars-d-learn

On Friday, 20 November 2015 at 15:03:06 UTC, Adam D. Ruppe wrote:

On Friday, 20 November 2015 at 14:18:00 UTC, Alex Parrill wrote:
But you don't need a template for this case; mixin templates 
have access to `this`:


Indeed, this is a good answer too.

The difference between this and the template thing I did is 
that yours is virtual so calling it through an interface will 
work even on subclasses. However, you must mix it into each sub 
class.


Mine is a template that only needs to be in the base 
class/interface, but also need a `this` of the derived type to 
see the derived type. (That's why I ran `this.bug();` in the 
constructor of B btw) If you call it on an variable typed as 
the interface, it will only show interface members.


IF i = new A();
i.bug(); // would only show interface members with mine

A a = new A();
a.bug(); // will now show A's members too

That's what the template this parameter does: the type of this 
at the *usage site* is passed as the parameter.



With your solution, the type of this at the *mixin site* is 
available.




I think your solution is generally better for stuff like 
serialization where you are passed an interface but need child 
members too. The template this param I used is nice for 
interface functions that need some kind of covariance; 
returning a type based on how it was used.


I review what I said before. Actually it doesn't work that well.

Using the two methods (yours or A.Parrill's one) the protected 
members in a class that's located in another module are not 
accessible, the relationship to the current class the traits code 
is ran into is totally lost and only public members are visible.


when bug() delcaration is `static void bug(T)(T t)`, pointer to 
members are get using __traits(getMember, t, member) and in your 
solution using _this instead of t. So it's a more for a less.