November 30, 2007
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
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
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

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
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
"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
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
"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
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
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