Thread overview
Template delegate/function ptr struct member
May 13, 2014
ed
May 13, 2014
Rikki Cattermole
May 13, 2014
uri
May 13, 2014
I'm porting some C++ code to D and a struct has the following member:

struct S
{
// ...
 //void* (*createMethod)();

void* function() createMethod;

}

I'd like to extend this as little to accept delegates for future use without breakage to existing code...

Is it possible to template this so "createMethod" can be a delegate() or function() of any type *and* have the compiler infer the type from ctor parameters?

For example:
---
struct S(F)
{
    // ...
    F createMethod;
    this(alias F)() {createMethod = &F;}
}
static void* func() {return null;}

void main() {
    auto s1 = S(&func);
    auto s2 = S(&Object.classinfo.create);

    // s1 is S!(void* function())
    // s2 is S!(Object delegate() const);
}
---

Is this a good idea or am I way off?

Thanks,
ed




May 13, 2014
On 13/05/2014 7:28 p.m., ed wrote:
> I'm porting some C++ code to D and a struct has the following member:
>
> struct S
> {
> // ...
>   //void* (*createMethod)();
>
> void* function() createMethod;
>
> }
>
> I'd like to extend this as little to accept delegates for future use
> without breakage to existing code...
>
> Is it possible to template this so "createMethod" can be a delegate() or
> function() of any type *and* have the compiler infer the type from ctor
> parameters?
>
> For example:
> ---
> struct S(F)
> {
>      // ...
>      F createMethod;
>      this(alias F)() {createMethod = &F;}
> }
> static void* func() {return null;}
>
> void main() {
>      auto s1 = S(&func);
>      auto s2 = S(&Object.classinfo.create);
>
>      // s1 is S!(void* function())
>      // s2 is S!(Object delegate() const);
> }
> ---
>
> Is this a good idea or am I way off?
>
> Thanks,
> ed

I would recommend going the route of property functions and using delegates as the default.

alias createMethodDel = void* delegate();
alias createMethodFunc = void* function();

struct S {
    private createMethodDel createMethod_;

    @property {
        createMethodDel createMethod() {
            return createMethod_;
        }

        void createMethod(createMethodDel func) {
            createMethod_ = func;
        }

        void createMethod(createMethodFunc func) {
            import std.functional : toDelegate;
            createMethod_ = toDelegate(func);
        }
    }
}

That way you know what you have access to is always callable and won't break any code.
May 13, 2014
On Tuesday, 13 May 2014 at 07:50:09 UTC, Rikki Cattermole wrote:
> On 13/05/2014 7:28 p.m., ed wrote:
>> I'm porting some C++ code to D and a struct has the following member:
>>
>> struct S
>> {
>> // ...
>>  //void* (*createMethod)();
>>
>> void* function() createMethod;
>>
>> }
>>
>> I'd like to extend this as little to accept delegates for future use
>> without breakage to existing code...
>>
>> Is it possible to template this so "createMethod" can be a delegate() or
>> function() of any type *and* have the compiler infer the type from ctor
>> parameters?
>>
>> For example:
>> ---
>> struct S(F)
>> {
>>     // ...
>>     F createMethod;
>>     this(alias F)() {createMethod = &F;}
>> }
>> static void* func() {return null;}
>>
>> void main() {
>>     auto s1 = S(&func);
>>     auto s2 = S(&Object.classinfo.create);
>>
>>     // s1 is S!(void* function())
>>     // s2 is S!(Object delegate() const);
>> }
>> ---
>>
>> Is this a good idea or am I way off?
>>
>> Thanks,
>> ed
>
> I would recommend going the route of property functions and using delegates as the default.
>
> alias createMethodDel = void* delegate();
> alias createMethodFunc = void* function();
>
> struct S {
>     private createMethodDel createMethod_;
>
>     @property {
>         createMethodDel createMethod() {
>             return createMethod_;
>         }
>
>         void createMethod(createMethodDel func) {
>             createMethod_ = func;
>         }
>
>         void createMethod(createMethodFunc func) {
>             import std.functional : toDelegate;
>             createMethod_ = toDelegate(func);
>         }
>     }
> }
>
> That way you know what you have access to is always callable and won't break any code.

I was so focused on a template solution that I never even thought of doing it that way, nice one :)


Thanks,
ed