www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Unintuitive behavior with shared classes & template member functions;

reply Jaime <benjamin.i.mccann gmail.com> writes:
Some code that produces the strange behavior I'm seeing:

```d
shared class MyClass {
     this() {}
     this(As...)(As args) if (As.length > 0) {}
}

void main() {
     pragma(msg, typeof(new MyClass));
     pragma(msg, typeof(new MyClass(1, 2, 3, "hello world")));
     pragma(msg, typeof(new shared(MyClass)));
     pragma(msg, typeof(new shared(MyClass)(1, 2, 3, "hello 
world")));
}
```

Expected output of compilation:

```
shared(MyClass)
shared(MyClass)
shared(MyClass)
shared(MyClass)
```

Actual output of compilation:

```
test.d(7): Error: none of the overloads of `__ctor` are callable 
using a non-shared object, candidates are:
test.d(2):        `test.MyClass.this()`
test.d(3):        `__ctor(As...)(As args)`
   with `As = ()`
   must satisfy the following constraint:
`       As.length > 0`
_error_
MyClass
shared(MyClass)
test.d(10): Error: none of the overloads of `this` are callable 
using argument types `(int, int, int, string) shared`, candidates 
are:
test.d(2):        `test.MyClass.this()`
test.d(3):        `__ctor(As...)(As args)`
_error_
```

Compiler version: 64-bit, v2.096.1, on Linux

What this seems to illustrate is that template member functions 
of a shared class are not implicitly shared. Alarmingly, this 
example illustrates this is true specifically for template 
constructors, meaning if a shared class has a template 
constructor that's not explicitly shared, it's possible to 
construct a non-shared instance of the shared class.

Why does this happen? Is it intended behavior? I'm still somewhat 
new to D, so I'm not prepared to submit this as an issue quite 
yet; for all I know, there might be a good reason it works this 
way.

This confusing problem really bit me in the patootie in a 
personal project earlier. Fortunately, although it was difficult 
to guess what was going on, once I did, it was an easy fix: 
namely, a template member function explicitly marked as shared 
is, of course, compiled as shared, as desired.
Jan 14 2022
parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 1/14/22 6:10 PM, Jaime wrote:

 Why does this happen? Is it intended behavior? I'm still somewhat new to 
 D, so I'm not prepared to submit this as an issue quite yet; for all I 
 know, there might be a good reason it works this way.
This seems like a bug to me.
 
 This confusing problem really bit me in the patootie in a personal 
 project earlier. Fortunately, although it was difficult to guess what 
 was going on, once I did, it was an easy fix: namely, a template member 
 function explicitly marked as shared is, of course, compiled as shared, 
 as desired.
I think it always be shared. Alarmingly, if you have a method, you can't call it on your newly constructed non-shared object (because the object isn't shared, but the method is). shared classes on their own are kind of junk. It's supposed to mean that everything is shared inside, but you probably can fix the issue via: ```d class C { shared: ... // everything } ``` Please file: https://issues.dlang.org -Steve
Jan 14 2022
parent Jaime <benjamin.i.mccann gmail.com> writes:
On Saturday, 15 January 2022 at 02:52:20 UTC, Steven 
Schveighoffer wrote:
 you probably can fix the issue via:

 ```d
 class C
 {
 shared:
    ... // everything
 }
 ```
This seems like a good solution. To achieve implicit sharing on the aggregate itself, I can use this approach to define a [Voldemort type](https://wiki.dlang.org/Voldemort_types), and declare the intended name as an externally visible alias to that type. Something like this (untested): ```d alias MyClass = shared(typeof(({ class MyInvisibleClass {shared { // things }} return cast(MyInvisibleClass)(null); })())); ``` Whether this is a good thing to do, of course, is debatable.
 Please file:  https://issues.dlang.org

 -Steve
Unfortunately I cannot; despite my repeated attempts, the Bugzilla instance is not sending me a confirmation email to register an account. This problem has persisted for a day or so, so I doubt the emails will eventually come through. I apologize. If anyone reading would care to file this issue on my behalf, I would be much obliged.
Jan 16 2022