digitalmars.D.learn - multiqualifier
- sclytrack (218/218) Jun 16 2018 I'm going to post this in learn in order not to disturb "the
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(); ---
Jun 16 2018