Implicit conversions for AA keys
Timon Gehr
timon.gehr at gmx.ch
Sat Mar 24 04:34:56 PDT 2012
On 03/24/2012 01:20 AM, H. S. Teoh wrote:
> On Fri, Mar 23, 2012 at 10:53:10PM +0100, Timon Gehr wrote:
>> On 03/23/2012 10:07 PM, Timon Gehr wrote:
>>>
>>> I see. An alternative solution (one that does not make AAs depend on
>>> Phobos and is more slick) would be to use the const qualified key type
>>> for lookup (that is what const is for) and to have immutable keys for
>>> stores. For types that define .idup, there would be another overload of
>>> opIndexAssign that can take a const qualified key.
>>
>> Proof of concept:
> [...]
>
> Hmm. I decided that perhaps the full-fledged std.conv.to is a bit of an
> overkill, so I revised the AA code to compromise between needing
> std.conv.to and still deliver what Andrei wants.
>
> Basically, I have a template that defines AA key compatibility, where
> compatibility means that given an AA with key type Key and a key k of
> type K, k is considered compatible if:
>
> - k==K.init is valid (i.e. they can be compared);
> - (At least) one of the following holds:
> - is(immutable(K) == immutable(Key))
> - is(typeof(k.idup) == Key)
> - Key is a static array of length N, and k[0..N] is valid.
> - is(K : Key)
>
> For the first case (is(immutable(K)==immutable(Key)), which means K and
> Key have the "same representation") and the second case (K.idup yields
> Key), we can basically assume that K.toHash() is consistent with
> Key.toHash(). When creating a new entry, we just assign K to Key, or
> K.idup to Key as necessary.
>
> For the third case, we can just slice the input array when comparing or
> assigning to a new entry (this will throw an Error if the input array
> has the wrong length). I decided to be permissive and compute the hash
> on the entire array, if the length doesn't match it will fail anyway, so
> it's OK to lookup an array of mismatching length in an AA with static
> array keys, as long as you don't try to store the key into it.
>
> Lastly, if is(K : Key) holds but none of the others do, then convert the
> key before computing the hash:
>
> Key key = k; // implicit conversion
> return key.toHash();
>
> This ensures the int->double conversion works correctly. Creating a new
> entry can just use straight assignment, due to the implicit conversion.
>
> I've added these changes on github in a branch:
>
> https://github.com/quickfur/New-AA-implementation/tree/keyconv
>
> Andrei, please try it out and see if it works on the cases you have in
> mind. :-)
>
>
> T
>
This solution creates unnecessary template bloat for every implicit
conversion, duplicates compiler logic, and I think it does not work
correctly because of other issues. I have refined my proof of concept.
Consider this:
template getConstQual(T){
static if(is(T _ == immutable(U),U)) alias const(getConstQual!U) r;
else static if(is(T _ == const(U),U)) alias const(getConstQual!U) r;
else static if(is(T _ == inout(U),U)) alias const(getConstQual!U) r;
else static if(is(T _ == shared(U),U)) alias const(getConstQual!U) r;
else static if(is(T _ == U[],U)) alias const(getConstQual!U[]) r;
else static if(is(T _ == U*,U)) alias const(getConstQual!U*) r;
else alias const(T) r;
alias r getConstQual;
}
struct AA(Key, Value) if(is(Key==immutable(Key))){
Value[Key] payload;
auto opIndex(getConstQual!Key k){return payload[cast(immutable)k];}
auto opIndexAssign(Value v, Key k){return payload[cast(immutable)k]=v;}
static if(is(typeof(getConstQual!Key.init.idup):Key)){
auto opIndexAssign(Value v, getConstQual!Key k){
if(auto p = (cast(immutable)k) in payload) return *p=v;
return this[k.idup]=v;
}
}
}
template AA(Key, Value)
if(!is(Key==immutable(Key))&&is(Key:immutable(Key))){
alias AA!(immutable(Key), Value) AA;
}
void main() {
AA!(immutable(double)[], int) aa;
aa[[1.0,2.0,3.0]]=2; // works, with no .idup!
aa[[1,2,3]]=2; // ditto
AA!(dstring,int) ab;
ab["123"]=2; // just works
char[3] c= "123";
AA!(short,int) ac;
ac[2]=2; // so does this
}
This nicely resolves all the implementation problems you have
encountered/will encounter, because it does not rely on IFTI. I think
you should follow this strategy.
More information about the Digitalmars-d
mailing list