December 01, 2018
After some refactoring, there are four functions sharing the same name (technically four, but LDC didn't complain about them):

@nogc void blitter(T)(T* src, T* dest, size_t length){...}

and

@nogc void blitter(T)(T* src, T* dest, size_t length, T* mask){...}

I need the first one, but at compilation time I get the following error:

pixelperfectengine\src\PixelPerfectEngine\graphics\layers.d(61,30): Error: template CPUblit.composing.blitter matches more than one template declaration:
..\..\..\AppData\Local\dub\packages\cpublit-0.2.3\cpublit\src\CPUblit\composing.d(2006,19):     blitter(T)(T* src, T* dest, size_t length)
and
..\..\..\AppData\Local\dub\packages\cpublit-0.2.3\cpublit\src\CPUblit\composing.d(2274,19):     blitter(T)(T* src, T* dest, size_t length, T* mask)
November 30, 2018
On Sat, Dec 01, 2018 at 01:17:55AM +0000, solidstate1991 via Digitalmars-d-learn wrote:
> After some refactoring, there are four functions sharing the same name (technically four, but LDC didn't complain about them):
> 
> @nogc void blitter(T)(T* src, T* dest, size_t length){...}
> 
> and
> 
> @nogc void blitter(T)(T* src, T* dest, size_t length, T* mask){...}
> 
> I need the first one, but at compilation time I get the following error:
> 
> pixelperfectengine\src\PixelPerfectEngine\graphics\layers.d(61,30): Error: template CPUblit.composing.blitter matches more than one template declaration:
> ..\..\..\AppData\Local\dub\packages\cpublit-0.2.3\cpublit\src\CPUblit\composing.d(2006,19):     blitter(T)(T* src, T* dest, size_t length)
> and
> ..\..\..\AppData\Local\dub\packages\cpublit-0.2.3\cpublit\src\CPUblit\composing.d(2274,19):     blitter(T)(T* src, T* dest, size_t length, T* mask)

For non-template overloaded functions, you can get the address by casting the function pointer, e.g.:

	void fun(int size) {
		writeln("1");
	}

	void fun(int size, float z) {
		writeln("2");
	}

	auto p1 = cast(void function(int)) &fun;
	auto p2 = cast(void function(int, float)) &fun;
	auto p3 = cast(void function(int, string)) &fun;

	p1(0);		// prints "1"
	p2(0, 0f);	// prints "2"
	p3(0, "");	// prints "1" (!)

It's sorta weird when the cast doesn't match any overload; the compiler seems to just arbitrarily select the first one.

However, for template functions, casting isn't enough; you need
__traits(getOverloads):

	alias ovs = __traits(getOverloads, myModule, "gun", true);
	foreach (ov; ovs) {
		writeln(ov.stringof);
	}

prints:

	gun(T)(T t, int size)
	gun(T)(T t, int size, float z)

But actually coaxing the address out of the function is rather ugly:

	// These don't work:
	//auto q = &ovs[0]!int;
	//auto q = &(ovs[0]!int);
	//auto q = &(ovs[0])!int;
	// ... etc.

	// But this does:
	alias ov1 = ovs[1];
	auto q = &ov1!int;
	q(0, 1, 1f);	// prints "4"

However, there appears to be a bug: if you try to access the first overload, it doesn't work again!

	// But this does:
	alias ov0 = ovs[0];	// NG: compile error!
	auto q = &ov0!int;
	q(0, 1, 1f);

Sounds like a compiler bug should be filed. :-/

I tried to hack it by using AliasSeq to insert a dummy first element to the sequence then using [1] to access the first overload, but got the same error. I guess internally somehow the compiler isn't treating the first overload case correctly, independently of its position in the tuple / AliasSeq.


T

-- 
Nearly all men can stand adversity, but if you want to test a man's character, give him power. -- Abraham Lincoln