Compiler fails to match array literal to byte[] in templated functions (Was: Re: More putrid beef soup (Was: Re: Implicit string lit conversion) to wstring/dstring)

H. S. Teoh hsteoh at quickfur.ath.cx
Sun Mar 18 20:40:55 PDT 2012


OK, perhaps the previous subject line of the previous post deterred
people from actually reading the contents. :-(

Basically, I'm trying to address Andrei's request that this should work
with my AA implementation:

	int[dstring] aa;
	aa["abc"] = 1;	// "abc" implicitly deduced as dstring

Currently, for maximum usability, the code allows any type to be
supplied for the key, as long as it can be implicitly converted to the
AA's key type. This is implemented as:

	opIndexAssign(K)(Value v, K key) if (implicitConvertible!K) {}

However, this causes a problem with dstring and wstring, because a
literal like "abc" defaults to string rather than dstring or wstring, so
when the compiler tries to find a match for opIndexAssign, it sees that
string can't implicitly convert to dstring, so it produces an error.

This doesn't happen if opIndexAssign was simply:

	opIndexAssign(Value v, Key key) {}

where Key==dstring, because then the compiler implicitly deduces "abc"
as a dstring.

In order to fix this, one fix is:

	// Key==dstring
	opIndexAssign()(Value v, Key key) { __opIndexAssignImpl(v,key); }
	opIndexAssign(K)(Value v, K key)
		if (implicitConvertible!K && !is(K==string))
	{
		__opIndexAssignImpl(v,key);
	}

How this works is, when the compiler sees "abc", it first tries to match
opIndexAssign(K=string)(Value,K), defaulting "abc" to string, but the
signature constraint declines, so the compiler tries
opIndexAssign()(Value v, dstring key), which matches with "abc" as
dstring.

This works for string, wstring, and dstring.

However, the compiler seems to handle numerical literals like [1,2,3]
differently. For example:

	void func(byte[] b) {}
	func([1,2,3]);		// OK

However:

	void func()(byte[] b) {}
	func([1,2,3]);		// Does not match template

Because of this, it's basically impossible to make literals like [1,2,3]
work with AA's with key type byte[], short[], etc., because [1,2,3] will
never match byte[] in a templated function, and int[] cannot be
implicitly converted to byte[]. So it is impossible to replicate the
implicit conversion in code like:

	byte[] b;
	b = [1,2,3];

without compiler changes. :-(


--T


More information about the Digitalmars-d mailing list