Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Interchanging delegate/function and interface in D2

I'd like to be able to define a function that takes an interface, but can be fulfilled with a delegate or function that provide the same functionality. For example, in C++ I can write something like:

typedef std::function<int (float)> toInt;

void fun(toInt dg) { ... }

struct impl1 {
    int operator()(float x) { ... }
};

int impl2(float x) { ... }

And then call it using either implementation:

fun(impl1());
fun(&impl2);

(This float->int conversion is just a simplified example to illustrate the principle, not my actual functionality).

I'd like to achieve something similar in D. My naive attempt went like this:

interface toInt {
    int opCall(float);
}

void fun(toInt dg) { ... }

int impl2(float x) { ... }

fun(impl2);

The compiler complains on this last line that it cannot implicitly convert impl2 to toInt type. I can probably just add an overloaded implementation of fun and make the conversion explicit, but I was wondering if there was a more elegant and general way of doing this, as in the C++ example above.

like image 740
Eitan Avatar asked Sep 07 '10 23:09

Eitan


People also ask

What will happen if a delegate has a non void return type?

When the return type is not void as above in my case it is int. Methods with Int return types are added to the delegate instance and will be executed as per the addition sequence but the variable that is holding the return type value will have the value return from the method that is executed at the end.

How many types of delegates are there in C#?

There are three types of delegates that can be used in C#.

Why should we use delegates in C#?

Delegates allow methods to be passed as parameters. Delegates can be used to define callback methods. Delegates can be chained together; for example, multiple methods can be called on a single event. Methods don't have to match the delegate type exactly.

What operator do you use to refer a delegate to a method it will invoke?

After setting a target method, a delegate can be invoked using the Invoke() method or using the () operator. del. Invoke("Hello World!"); // or del("Hello World!");


1 Answers

he_the_great has it basically right, but the following small change will make it work with opCall enabled structures/classes as well.

import std.conv;
import std.stdio;
import std.traits;

void fun ( T ) ( float value, T pred )
if ( __traits( compiles, pred( value ) ) && is( ReturnType!pred : int ) )
{
    writefln( "pred( %f ) -> %s", value, pred( value ) );
}

struct impl1 {
    int opCall ( float f ) {
        return to!int( f );
    }
}

int impl2 ( float f ) {
    return to!int( f );
}

void main () {
    impl1 x;
    fun( 1.0, x );

    fun( 2.0, &impl2 );

    fun( 3.0, ( float f ){ return to!int( f ); } );
}
like image 144
Chris Nicholson-Sauls Avatar answered Oct 13 '22 13:10

Chris Nicholson-Sauls