View mode: basic / threaded / horizontal-split · Log in · Help
November 30, 2007
Determining whether a class has a method
Hey all,

I'm trying to determine whether a class has a method (at compile time, 
based on the name), and ideally I want to do this is D1 as well as D2. 
In D2, I can just use __traits, of course.

I could try doing something like:

bool has_method(T, string name)() {
    foreach (method; T.tupleof) {
        if (method.stringof == name) {
            return true;
        }
    }
    return false;
}

But tupleof fails if you give it a class that has fields (methods are 
fine, but data fields aren't). I'm pretty sure this is a bug; can anyone 
else comment on it?

Is there a way to do this in D1?
November 30, 2007
Re: Determining whether a class has a method
Christopher Wright wrote:
> Hey all,
> 
> I'm trying to determine whether a class has a method (at compile time, 
> based on the name), and ideally I want to do this is D1 as well as D2. 
> In D2, I can just use __traits, of course.
> 
> I could try doing something like:
> 
> bool has_method(T, string name)() {
>     foreach (method; T.tupleof) {
>         if (method.stringof == name) {
>             return true;
>         }
>     }
>     return false;
> }
> 
> But tupleof fails if you give it a class that has fields (methods are 
> fine, but data fields aren't). I'm pretty sure this is a bug; can anyone 
> else comment on it?
> 
> Is there a way to do this in D1?

I think you may be able to use an 'is' check + string mixin if the name 
string is a compile time constant.
like
   static if(is( T.name == function ))

then mixin-ify that like

bool has_method(T, string name) {
   mixin("static if(is T."~name~" == function)) "
         "{ return true; } else {return false; }");
}


--bb
November 30, 2007
Re: Determining whether a class has a method
Bill Baxter wrote:
> I think you may be able to use an 'is' check + string mixin if the name 
> string is a compile time constant.
> like
>    static if(is( T.name == function ))
> 
> then mixin-ify that like
> 
> bool has_method(T, string name) {
>    mixin("static if(is T."~name~" == function)) "
>          "{ return true; } else {return false; }");
> }
> 
> 
> --bb

Very nice! It works for every situation but the one I need:

static if (is (T._ctor == function)) {
   // This never happens.
}

If there's no constructor defined for a class or any of its base 
classes, then ParameterTypeTuple!(T._ctor) fails, of course.

I guess I can work around this by requiring an explicit constructor, but 
I don't love it, especially since I can't provide a helpful error 
message in the failing case.
November 30, 2007
Re: Determining whether a class has a method
Christopher Wright wrote:
> Bill Baxter wrote:
>> I think you may be able to use an 'is' check + string mixin if the
>> name string is a compile time constant.
>> like
>>    static if(is( T.name == function ))
>>
>> then mixin-ify that like
>>
>> bool has_method(T, string name) {
>>    mixin("static if(is T."~name~" == function)) "
>>          "{ return true; } else {return false; }");
>> }
>>
>>
>> --bb
> 
> Very nice! It works for every situation but the one I need:
> 
> static if (is (T._ctor == function)) {
>    // This never happens.
> }
> 
> If there's no constructor defined for a class or any of its base
> classes, then ParameterTypeTuple!(T._ctor) fails, of course.
> 
> I guess I can work around this by requiring an explicit constructor, but
> I don't love it, especially since I can't provide a helpful error
> message in the failing case.

Can't you do something like:

static if( is( typeof(new T) == T ) ) ...

That should fail if T doesn't have a zero-arg constructor, at least AFAIK.

	-- Daniel
November 30, 2007
Re: Determining whether a class has a method
Daniel Keep wrote:
> 
> Christopher Wright wrote:
>> Bill Baxter wrote:
>>> I think you may be able to use an 'is' check + string mixin if the
>>> name string is a compile time constant.
>>> like
>>>    static if(is( T.name == function ))
>>>
>>> then mixin-ify that like
>>>
>>> bool has_method(T, string name) {
>>>    mixin("static if(is T."~name~" == function)) "
>>>          "{ return true; } else {return false; }");
>>> }
>>>
>>>
>>> --bb
>> Very nice! It works for every situation but the one I need:
>>
>> static if (is (T._ctor == function)) {
>>    // This never happens.
>> }
>>
>> If there's no constructor defined for a class or any of its base
>> classes, then ParameterTypeTuple!(T._ctor) fails, of course.
>>
>> I guess I can work around this by requiring an explicit constructor, but
>> I don't love it, especially since I can't provide a helpful error
>> message in the failing case.
> 
> Can't you do something like:
> 
> static if( is( typeof(new T) == T ) ) ...
> 
> That should fail if T doesn't have a zero-arg constructor, at least AFAIK.
> 
> 	-- Daniel

With the implication that, if I have a zero-arg constructor, I can just 
use that, and if I don't, then I can safely call ParameterTypeTuple on 
it. Thanks!
November 30, 2007
Re: Determining whether a class has a method
"Christopher Wright" <dhasenan@gmail.com> wrote in message 
news:fink7k$6ph$1@digitalmars.com...

> But tupleof fails if you give it a class that has fields (methods are 
> fine, but data fields aren't). I'm pretty sure this is a bug; can anyone 
> else comment on it?

tupleof is supposed to give you a tuple of fields.  It will never give 
methods.
November 30, 2007
Re: Determining whether a class has a method
Jarrett Billingsley wrote:
> "Christopher Wright" <dhasenan@gmail.com> wrote in message 
> news:fink7k$6ph$1@digitalmars.com...
> 
>> But tupleof fails if you give it a class that has fields (methods are 
>> fine, but data fields aren't). I'm pretty sure this is a bug; can anyone 
>> else comment on it?
> 
> tupleof is supposed to give you a tuple of fields.  It will never give 
> methods. 
> 
> 

And it's supposed to work for classes?
November 30, 2007
Re: Determining whether a class has a method
"Christopher Wright" <dhasenan@gmail.com> wrote in message 
news:finqpt$lnj$2@digitalmars.com...
> Jarrett Billingsley wrote:
>> "Christopher Wright" <dhasenan@gmail.com> wrote in message 
>> news:fink7k$6ph$1@digitalmars.com...
>>
>>> But tupleof fails if you give it a class that has fields (methods are 
>>> fine, but data fields aren't). I'm pretty sure this is a bug; can anyone 
>>> else comment on it?
>>
>> tupleof is supposed to give you a tuple of fields.  It will never give 
>> methods.
>
> And it's supposed to work for classes?

Yes.  It's all in the spec:
Class Properties
The .tupleof property returns an ExpressionTuple of all the fields in the 
class, excluding the hidden fields and the fields in the base class.
November 30, 2007
Re: Determining whether a class has a method
Jarrett Billingsley wrote:
> "Christopher Wright" <dhasenan@gmail.com> wrote in message 
> news:finqpt$lnj$2@digitalmars.com...
>> Jarrett Billingsley wrote:
>>> "Christopher Wright" <dhasenan@gmail.com> wrote in message 
>>> news:fink7k$6ph$1@digitalmars.com...
>>>
>>>> But tupleof fails if you give it a class that has fields (methods are 
>>>> fine, but data fields aren't). I'm pretty sure this is a bug; can anyone 
>>>> else comment on it?
>>> tupleof is supposed to give you a tuple of fields.  It will never give 
>>> methods.
>> And it's supposed to work for classes?
> 
> Yes.  It's all in the spec:
> Class Properties
> The .tupleof property returns an ExpressionTuple of all the fields in the 
> class, excluding the hidden fields and the fields in the base class.

Ah. Then it's not supposed to generate an error:
Error: type Foo is not an expression

For reference, here's the code, and I think it's not my error:

class Foo {
// Comment the following line to eliminate the error:
// Error: type Foo is not an expression
   int i;
}

foreach (blah; Foo.tupleof) {
   writefln("%s", blah.stringof);
}
// or:
auto a = Foo.tupleof[0];
November 30, 2007
Re: Determining whether a class has a method
Christopher Wright wrote:
> Jarrett Billingsley wrote:
>> "Christopher Wright" <dhasenan@gmail.com> wrote in message 
>> news:finqpt$lnj$2@digitalmars.com...
>>> Jarrett Billingsley wrote:
>>>> "Christopher Wright" <dhasenan@gmail.com> wrote in message 
>>>> news:fink7k$6ph$1@digitalmars.com...
>>>>
>>>>> But tupleof fails if you give it a class that has fields (methods 
>>>>> are fine, but data fields aren't). I'm pretty sure this is a bug; 
>>>>> can anyone else comment on it?
>>>> tupleof is supposed to give you a tuple of fields.  It will never 
>>>> give methods.
>>> And it's supposed to work for classes?
>>
>> Yes.  It's all in the spec:
>> Class Properties
>> The .tupleof property returns an ExpressionTuple of all the fields in 
>> the class, excluding the hidden fields and the fields in the base class.
> 
> Ah. Then it's not supposed to generate an error:
> Error: type Foo is not an expression
> 
> For reference, here's the code, and I think it's not my error:
> 
> class Foo {
> // Comment the following line to eliminate the error:
> // Error: type Foo is not an expression
>    int i;
> }
> 
> foreach (blah; Foo.tupleof) {
>    writefln("%s", blah.stringof);
> }
> // or:
> auto a = Foo.tupleof[0];

Foo is a type.  So Foo.tupleof would be a type tuple (if anything -- I'm 
not sure that works, though it does for structs).

You probably need

    auto a = (new Foo).tupleof[0];

--bb
« First   ‹ Prev
1 2
Top | Discussion index | About this forum | D home