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.
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.
There are three types of delegates that can be used 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.
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!");
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 ); } );
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With