Something like ADL from C++?

Arafel er.krali at gmail.com
Fri Dec 6 09:46:55 UTC 2024


On 6/12/24 9:05, Richard (Rikki) Andrew Cattermole wrote:
> I'm fully aware of template this parameters, I was trying to get them to 
> work 10 years ago.
> 
> They have problems that prevent their usage.
> 
> 1. They are templates, so not in vtable
> 2. They require the this pointer to be typed to the child (extremely 
> easy for this to not be the case, see 1)
> 3. Because they are not virtual, you cannot up cast (see 2)
> 4. Cannot be over ridden for any manual behavior
> 
> All and all, they become very complex for common usage, quite fragile if 
> you don't use them right, not the kind of thing you recommend to people 
> who are use to runtime reflection.

That's true, I found a workaround using constructors and registering 
classes there, but currently it only works with one level of inheritance 
(without user intervention, the whole purpose of it):

```d
import std;

class SerializationRoot {
     static void function()[TypeInfo_Class] serializationMethods;
     // We would need a `shared static` constructor that would be always 
called
     /* shared static */ this(this T)() {
         auto myType = typeid(T);
         if (myType !in serializationMethods) {
             writeln("Registering type ", myType);
             serializationMethods[myType] = 
(&T.serializeDefaultImpl!T).funcptr;
         }
     }
     void serialize() {
         auto myType = typeid(this);
         assert(myType in serializationMethods, "The class was not 
registered for default serialization.");
         void delegate() dlg;
         dlg.funcptr = serializationMethods[myType];
         dlg.ptr = cast (void *) this;
         dlg();
         stdout.flush;
     }
     void serializeDefaultImpl(T)() {
         T realThis = cast(T) this;
         writeln("Default serialization for ", typeid(realThis));
     }
}

class MyClass : SerializationRoot { }

class MyOtherClass : SerializationRoot {
     this(int) { }
     override void serialize() {
         writeln("This class does something special, but still uses the 
default mechanism.");
         super.serialize;
     }
}

class MySpecialClass : SerializationRoot {
     override void serialize() {
         writeln("This class disregards everything takes everything into 
its own hands.");
     }
}

class MyProblematicClass : MyClass { }

void main() {
     SerializationRoot myClass = new MyClass;
     SerializationRoot myOtherClass = new MyOtherClass(1);
     SerializationRoot mySpecialClass = new MySpecialClass();
     SerializationRoot myProblematicClass = new MyProblematicClass();
     myClass.serialize;
     myOtherClass.serialize;
     mySpecialClass.serialize;
     myProblematicClass.serialize; // BOOM!
}
```

But it should work as expect if we had templated-this (shared) static 
constructors. My reading is that they are actually not forbidden in the 
spec ("member functions" should include static ones too) [1], and there 
is already an open bug for that [2] (with some duplicates).

Unfortunately I don't think it'll happen anytime soon, and I don't have 
the skills to have a go at it myself.

[1]: https://dlang.org/spec/template.html#template_this_parameter
[2]: https://issues.dlang.org/show_bug.cgi?id=10488



More information about the Digitalmars-d mailing list