D style - member functions

Basile B. b2.temp at gmx.com
Wed Apr 26 21:35:19 UTC 2023


On Wednesday, 26 April 2023 at 18:24:08 UTC, DLearner wrote:
> Consider:
> ```
> struct S1 {
>    int A;
>    int B;
>    int foo() {
>       return(A+B);
>    }
> }
>
> struct S2 {
>    int A;
>    int B;
> }
> int fnAddS2(S2 X) {
>    return (X.A + X.B);
> }
>
> void main() {
>    import std.stdio : writeln;
>
>    S1 Var1 = S1(1, 2);
>    writeln("Total Var1 = ", Var1.foo());
>
>    S2 Var2 = S2(1, 2);
>    writeln("Total Var2 = ", fnAddS2(Var2));
>
>    return;
> }
> ```
>
> Of the two ways shown of producing the total from the same 
> underlying structure, which is the better style?


To make both version really equivalent you should rather write

     int fnAddS2(ref S2 X) {
         return (X.A + X.B);
     }

the `this` for the member functions is a reference as obviously 
you want to eventually mutate the members and not their copy. 
What happened in your `fnAddS2` is that the whole stuff was 
blitted and mutation of the members would have no effect on the 
argument used in the call.

> Further, do we care about the situation where there are many 
> variables of type 'S', which presumably means the function code 
> generated from S1 gets duplicated many times, but not so with 
> S2?

Your presumption is wrong. The code generated for a function is 
not regenerated per instance. One version is enough to handle all 
the instances as the instance is itself a parameter of the 
function. What is happening for `foo()`, i.e the member function, 
is that there is an hidden parameter. Depending on the language 
the way the hidden argument is read might be slightly different 
but you really should consider that

     struct S1 {
         int A;
         int B;
         int foo() {
            return(A+B);
         }
     }

is like

     struct S1 {
         int A;
         int B;
         static int foo(ref S1 that) {
            return(that.A+that.B);
         }
     }

or

     struct S1 {
         int A;
         int B;
     }

     int foo(ref S1 that) {
        return(that.A+that.B);
     }

One problem of the hidden parameter is that for example

     int foo(const ref S1 that) {
        return(that.A+that.B);
     }

cannot be expressed (at first glance)... how to qualify `const` 
something that is hidden ? It's actually possible using a member 
function attribute:

     struct S1 {
         int A;
         int B;
         int foo() const /*const is for the hidden parameter*/ {
            return(A+B);
         }
     }



More information about the Digitalmars-d-learn mailing list