www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - how to determine if type is final/abstract

reply "JS" <js.mdnq gmail.com> writes:
I have some code that needs to determine if a type 
isFinalFunction or isAbstractFunction but they don't seem to work:

     foreach(k, t; TargetMembers)
     {
         alias TypeTuple!(t.type)[0] type;
         if (isFinalFunction!(t)) { ... }
     }

the if statement never gets executed. I've tried using type 
instead of t and various other things. I suppose the

the function is defined as

final string foo() { ...}

but TargetMembers is

"tuple(FuncInfo!("foo", pure nothrow  safe string()), 
FuncInfo!("Value",  property int()), FuncInfo!("Value",  property 
int(int value)))"

I believe the issue is that isFinalFunction requires an actual 
function symbol but I'm passing it a string?


How can I get this to work?
Jul 11 2013
next sibling parent reply "JS" <js.mdnq gmail.com> writes:
On Thursday, 11 July 2013 at 22:45:47 UTC, JS wrote:
 I have some code that needs to determine if a type 
 isFinalFunction or isAbstractFunction but they don't seem to 
 work:

     foreach(k, t; TargetMembers)
     {
         alias TypeTuple!(t.type)[0] type;
         if (isFinalFunction!(t)) { ... }
     }

 the if statement never gets executed. I've tried using type 
 instead of t and various other things. I suppose the

 the function is defined as

 final string foo() { ...}

 but TargetMembers is

 "tuple(FuncInfo!("foo", pure nothrow  safe string()), 
 FuncInfo!("Value",  property int()), FuncInfo!("Value", 
  property int(int value)))"

 I believe the issue is that isFinalFunction requires an actual 
 function symbol but I'm passing it a string?


 How can I get this to work?
much of the code used can be found at http://dpaste.dzfl.pl/209e260b. I can get the attributes of the function no problem and implement the interface except for final functions, which try to get implemented again... hence I need to prevent reimplementation of final functions but seem to have no way to determine if a function is final.
Jul 11 2013
parent "JS" <js.mdnq gmail.com> writes:
On Thursday, 11 July 2013 at 23:04:20 UTC, JS wrote:
 On Thursday, 11 July 2013 at 22:45:47 UTC, JS wrote:
 I have some code that needs to determine if a type 
 isFinalFunction or isAbstractFunction but they don't seem to 
 work:

    foreach(k, t; TargetMembers)
    {
        alias TypeTuple!(t.type)[0] type;
        if (isFinalFunction!(t)) { ... }
    }

 the if statement never gets executed. I've tried using type 
 instead of t and various other things. I suppose the

 the function is defined as

 final string foo() { ...}

 but TargetMembers is

 "tuple(FuncInfo!("foo", pure nothrow  safe string()), 
 FuncInfo!("Value",  property int()), FuncInfo!("Value", 
  property int(int value)))"

 I believe the issue is that isFinalFunction requires an actual 
 function symbol but I'm passing it a string?


 How can I get this to work?
much of the code used can be found at http://dpaste.dzfl.pl/209e260b. I can get the attributes of the function no problem and implement the interface except for final functions, which try to get implemented again... hence I need to prevent reimplementation of final functions but seem to have no way to determine if a function is final.
I've also tried __traits and other stuff. I have access to the interface and I've tried hard coding the name and other stuff... Using them on simple example case works so it is an issue with the code, here is the full code: http://dpaste.dzfl.pl/16bc4a7e just mixin the templates to use use them, e.g., interface A(T) { final string foo() { return ""; } mixin tPropertyBuilder!(0, T); alias Value this; } class B(T) : A!T { property T Value() { return _value; } mixin tPropertyImplementer!(0, T); // implements foo, causes compile time error. should not implement final members. }
Jul 11 2013
prev sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2013-07-12 00:45, JS wrote:

 I believe the issue is that isFinalFunction requires an actual function
 symbol but I'm passing it a string?


 How can I get this to work?
Have you tried using a mixin? __traits(isFinalFunction, mixin(className ~ "." ~ member)); -- /Jacob Carlborg
Jul 11 2013
next sibling parent "JS" <js.mdnq gmail.com> writes:
On Friday, 12 July 2013 at 06:38:54 UTC, Jacob Carlborg wrote:
 On 2013-07-12 00:45, JS wrote:

 I believe the issue is that isFinalFunction requires an actual 
 function
 symbol but I'm passing it a string?


 How can I get this to work?
Have you tried using a mixin? __traits(isFinalFunction, mixin(className ~ "." ~ member));
yes, I've tried something similar(I used isFinalFunction). When I try it I get an error about the class not being found... I've tried to add the module name to it but it doesn't work. If I use your code directly on a simple test case it works as expected. Also, if the function is overloaded I do not think I can get it to work correctly?
Jul 12 2013
prev sibling parent reply "JS" <js.mdnq gmail.com> writes:
On Friday, 12 July 2013 at 06:38:54 UTC, Jacob Carlborg wrote:
 On 2013-07-12 00:45, JS wrote:

 I believe the issue is that isFinalFunction requires an actual 
 function
 symbol but I'm passing it a string?


 How can I get this to work?
Have you tried using a mixin? __traits(isFinalFunction, mixin(className ~ "." ~ member));
The issue is with the template being in a different module. Same code works fine when in the same module... module main; import std.stdio, std.cstream, std.conv, std.traits, testmodule; template test(alias i) { alias typeof(i) I; static string eval() { enum name = "foo"; //enum qname = moduleName!(I)~"."~I.stringof~"."~name; enum qname = I.stringof~"."~name; pragma(msg, "main: "~qname); return (__traits(isFinalFunction, mixin(qname))).stringof; } enum test = eval(); pragma(msg, "main: isfinal: "~test); } interface A { final void foo() { }; void foo(int x); } int main(string[] argv) { A a; writeln(mixin(test!(a))); writeln(mixin(test2!(a))); din.getc(); return 0; } testmodule.d: module testmodule; import std.traits; template test2(alias i) { alias typeof(i) I; static string eval() { enum name = "foo"; enum qname = moduleName!(I)~"."~I.stringof~"."~name; //enum qname = I.stringof~"."~name; pragma(msg, "testmodule: "~qname); return (__traits(isFinalFunction, mixin(qname))).stringof; } enum test2 = eval(); pragma(msg, "testmodule: isfinal: "~test2); } ------------ note test2 fails even though it is the same code. While this is probably a rather simple fix I would still have the problem of checking if an overloaded function is actually final rather than just the symbol name(which I guess is just the first function).
Jul 12 2013
parent reply "JS" <js.mdnq gmail.com> writes:
BTW, the error is

testmodule.d(14): Error: undefined identifier main

which suggests that the template can't find the module. I can 
import the module and it will work fine but this seems a bit 
circular. I will try and mixin the module to solve my original 
problem but still need to figure out how to handle overloads.
Jul 12 2013
parent reply Jacob Carlborg <doob me.com> writes:
On 2013-07-12 09:25, JS wrote:
 BTW, the error is

 testmodule.d(14): Error: undefined identifier main
Where does "main" come from?
 which suggests that the template can't find the module. I can import the
 module and it will work fine but this seems a bit circular. I will try
 and mixin the module to solve my original problem but still need to
 figure out how to handle overloads.
Try this: 1. Iterate over all members 2. Run __traits(getOverloads) for each member 3. Iterate all overloads 3. Run __traits(isFinalFunction) for each overload http://dlang.org/traits.html#getOverloads http://dlang.org/traits.html#allMembers http://dlang.org/traits.html#derivedMembers -- /Jacob Carlborg
Jul 12 2013
parent "JS" <js.mdnq gmail.com> writes:
On Friday, 12 July 2013 at 11:28:19 UTC, Jacob Carlborg wrote:
 On 2013-07-12 09:25, JS wrote:
 BTW, the error is

 testmodule.d(14): Error: undefined identifier main
Where does "main" come from?
 which suggests that the template can't find the module. I can 
 import the
 module and it will work fine but this seems a bit circular. I 
 will try
 and mixin the module to solve my original problem but still 
 need to
 figure out how to handle overloads.
Try this: 1. Iterate over all members 2. Run __traits(getOverloads) for each member 3. Iterate all overloads 3. Run __traits(isFinalFunction) for each overload http://dlang.org/traits.html#getOverloads http://dlang.org/traits.html#allMembers http://dlang.org/traits.html#derivedMembers
main is the main module. I've tried your method already but couldn't get it to work. I think it is ultimately flawed because one still needs to compare against the full definition. I was able to get it to work in any case by modifying std.traits. It has a more advanced GetOverloads template that ignores static functions. I included it to ignore final functions also... this might be a bug in the code as I'm sure if it wants to ignore static it probably should ignore finals. template isMethod(alias f) { static if (is(typeof(&f) F == F*) && is(F == function)) { enum isMethod = !__traits(isStaticFunction, f) && !__traits(isFinalFunction, f); } else enum isMethod = false; }
Jul 12 2013