June 16, 2018 multiqualifier | ||||
---|---|---|---|---|
| ||||
I'm going to post this in learn in order not to disturb "the guys". Multiqualifiers --------------- Warning: Stop reading if you don't have time. Tail-const rant in disguise. (1) Going from immutable to mutable, one layer deep. ----------------------------------- In the D programming language const(int ***) means the same as const int *** const int *** source; //head-const body-tail-const or just const const (int **)* destination; //head-mutable body-tail-const destination = source; //works with ldc2 (1.2.0) Assigning the source to the destination is possible and the head which was initially const becomes mutable. This is possible because a copy is made of that head pointer. const int *** source; //const const (int *)** destination; //head-body-mutable tail-const //error destination = source; //error Assigning the source to the destination is not possible because you would have to alter the initial head. To clarify with invalid D code (no-code). //warning: Fake D code const (int ***) source; const (int *)dup(*)dupchange(*) destination; const (int ****) source; const (int *)dup(*)dupchange(**) destination; So we don't do this altering of the values and go only one layer deep. The D programming language is even able to figure this one layer deep out with regard to structs. struct HeadMutableTailConst { const (int*) * pMutableHeadPointer; //head-mutable body-tail-const } const(HeadMutableTailConst) source; HeadMutableTailConst destination; //const-head to mutable-head with destination body-tail-const destination = source; //works with ldc2 (1.2.0) The important part is that the head is either mutable or const and the rest must always be body-tail-const. 1.a) Naming ----------- Starting to realize I need a different wording. The first pointer on the right is the head and the second pointer is the body. const(int ***)*** tailConst; //tail-const const(int ******) headTailConst; //head-const body-tail-const const(int *****)* bodyTailConst; //head-mutable body-tail-const Which means that body-tail-const can be either const(int ******) headTailConst; //head-const body-tail-const const(int *****)* bodyTailConst; //head-mutable body-tail-const body-tail-const completally ignores the head. (2) Going the other way. ------------------------ mutable can be assigned to const, and so does immutable. int *** source; const(int **)* destination; destination = source; //works The destination needs to be body-tail-const not just tail-const. int **** source; const(int*)*** destination; destination = source; //error struct Container1 { int * data; } struct Container2 { const(int) * data; } Container1 source; Container2 destination; destination = source; //error Both cases "mutable to const tail" and "const head to mutable head" with full BODY-TAIL-CONST (or recently head-mutability) (3) Multiple tails ------------------ 3.a --- A user defined type can have multiple tails so it should have multiple qualifiers, one for each tail. I've numbered them here with $1 and $2 in fake D code or no-code. //warning: Fake D code struct MultiTail { qual$1 (int) * a; //Mandatory BODY-TAIL-QUAL$1 or head-body-tail qual$2 (int) * b; //Mandatory BODY-TAIL-QUAL$2 this()(const, immutable) { //qual$1 is const //qual$2 is immutable } } (const, immutable) MultiTail a; //impossible D code. I'm going to be verbose so. The first "$1" becomes "const" and the second "$2" becomes immutable. Field "a" defined as const(int) * a; and the second field "b" is immutable(int) * b; I will use (const) for the multiqualifier between those (). (const) vs const 3.b --- warning: fake D code struct MultiTail { qual$1 (int) * a; //mandatory applied to body-tail or head-body-tail qual$1 (int) * b; qual$1 (int) * c; qual$2 (int) * z; } (const, immutable) MultiTail a; //impossible D code. A qualifier in a multitail qualifier applying to more tails then the number of qualifiers in a multiqualifier. 3.c --- Can you determine that a type is passable to a routine by just looking at the multiqualifier? (immutable, immutable) MultiTail parameter; void routine( (const, immutable) MultiTail a) { } 3.d classes Since classes are reference types. class MultiQualifiedType { qual$1(int) field; //mandatory on head-body-tail and not just body-tail for classes qual$2(int *) other; } (immutable, const) MultiQualifiedType a; Similarly for structs //-- struct HeadQualified { qual$1(int) field; } (const) HeadQualified * a; //a is body-tail-const //-- struct HeadMutableBodyTailQualified { qual$1(int) * field; } (const) HeadMutableTailQualified * a; //a is not body-tail-const error /-- 4. Faking it ------------ Containter!(const int) data; If you want to apply the qualifier to multiple fields you can separate it from the type. Container!(int, const) data; This creates a different type. Container!(int, immutable) data; The qualifier can not participate in the memory layout of the container. Let's say that Q1 is the first qualifier that you pass to the template. struct Container(T, Q1) { static if (is(Q1 == immutable)) { int * fieldThatExistsOnlyWhenImmutable; //error } } 5. multi-tail inout ------------------- With multi-tail maybe you don't want to pass (immutable) Container!(Element) to (const) Container!(Element) but to (inout) Container!(Element). //warning: fake D code inout(Element) findStuff( (inout) Container!(Element) cont) { } I guess you can only have one inout here or two inout but they are the same inout. So basically multiqualifiers for "Head-mutable multi-tail-inout" Container!(inout(Element)) //can't define field member as inout Container!(Element, inout) //faking it (inout) Container!(Element) //multiqualifier @tail(inout) Container!(Element) //previous tail const Do we want to number the inout? I'm too lazy to think. Post it anyways. //warning: all fake D code (inout$2, inout$1) Element findStuff( (inout$1, inout$2) Container!(Element) cont) { ... } --- class Base { qual$1(int) a; //mandatory head-body-tail for classes. qual$2(int) b; this() (inout, inout) { } } auto b = new (immutable, immutable) Base(); --- |
Copyright © 1999-2021 by the D Language Foundation