August 28, 2020
On Friday, 28 August 2020 at 01:26:58 UTC, Avrina wrote:
> On Friday, 28 August 2020 at 00:25:15 UTC, sarn wrote:
>>
>> None of that says anything about syntax, but it's why D doesn't have member function pointers, per se, like C++ does.
>
> D does technically have them. They just aren't type safe. As other people have said, the type should be either void*, or a delegate with a null data pointer.

I much prefer if people refrain from making bold statements that are not facts. D does not "technically" have member function pointers. Please don't confuse what is happening in assembly for some architecture with what the language guarantees. There is no guarantee that a delegate call is the same as a method call with implicit `this` parameter.

`&Struct.foo` currently has no meaning for non-static member function foo, so let's agree on fixing the compiler to error on it. If you want `&Struct.foo` to have a meaning, e.g. member function pointers, please write a DIP.

(sorry for the agitated email, I'm trying to make some progress here, instead of endless debate about something off-topic)

-Johan

August 27, 2020
On Fri, Aug 28, 2020 at 12:25:15AM +0000, sarn via Digitalmars-d wrote: [...]
> I don't know if you've seen them before, but these two articles
> explain the reasoning behind D not having member function pointers:
> https://www.drdobbs.com/cpp/member-function-pointers-in-d/231600610
> https://www.codeproject.com/Articles/7150/Member-Function-Pointers-and-the-Fastest-Possible
[...]

Thanks! I was on the fence before, but these two articles convinced me that member function pointers are not worth the trouble. Just use a delegate instead, or a lambda that receives the target object as a parameter:

	class C {
		void method1(int x);
		void method2(int y);
	}

	C c1 = ...;
	C c2 = ...;

	void function(C, int) mfp;
	mfp = (C self, int arg) { return self.method1(x); }
	mfp(c1, 1);	// calls c1.method1(1)
	mfp(c2, 1);	// calls c2.method1(1)

	mfp = (C self, int arg) { return self.method2(x); }
	mfp(c1, 1);	// calls c1.method2(1)
	mfp(c2, 1);	// calls c2.method2(1)

This works even if the method to be bound is static. None of the specialcasing and pathological corner-cases of actual member function pointers.

I say we should just forbid taking the address of non-static member functions.


T

-- 
To err is human; to forgive is not our policy. -- Samuel Adler
August 28, 2020
On Thursday, 27 August 2020 at 11:20:17 UTC, Johan wrote:
> Currently this code is not rejected by the compiler and instead creates non-functioning (undefined) code:
> ```
> struct S {
>     void foo() {}
> }
>
> void main() {
>     auto a = &S.foo;
> }
> ```
>
> See https://issues.dlang.org/show_bug.cgi?id=21195 .
>
> Considering https://www.digitalmars.com/articles/b68.html, why not simply reject `&S.foo` during semantic analysis?
>
> -Johan

As others have mentioned, it's possible to manually assemble a delegate from a context pointer and a function pointer. I've used this technique in my Objective-C bridge. In that case the context pointer (or this pointer for a class) came from Objective-C and the function pointer from D. Here's a link to the code for reference [1].

[1] http://dsource.org/projects/dstep/browser/dstep/objc/bridge/Bridge.d#L377

--
/Jacob Carlborg
1 2
Next ›   Last »