September 10, 2017 Re: -betterC and extern(C++) classes | ||||
---|---|---|---|---|
| ||||
Posted in reply to rikki cattermole | On Sunday, 10 September 2017 at 14:04:20 UTC, rikki cattermole wrote: > On 10/09/2017 2:19 PM, Moritz Maxeiner wrote: >> If TypeInfo for extern(C++) classes is removed, couldn't final extern(C++) classes without base class and which don't implement any interfaces omit the vtable so that the following assert holds: >> >> --- >> final extern(C++) class Foo {} >> static assert (__traits(classInstanceSize, Foo) == 0LU); >> --- >> >> The reason I ask is that fairly often I have an abstraction that's better suited as a reference type than a value type, but doesn't need any runtime polymorphy (or the monitor standard classes have). Structs + pointers are the only way I know of to avoid the (in this special case) unneeded vtable overhead, but it always ends up looking worse to read. > > We can do it for any class if its final. Even final classes can always inherit (potentially already overridden) virtual methods from their parent classes and since all normal D classes inherit from core.object : Object [1], which defines virtual methods (`toString`, `toHash`, `opCmp, and `opEquals`), I don't see how this can be true. > The problem isn't generating the vtable's. But the information required for casting. This applies to normal D classes, but D doesn't support (dynamic) casts for extern(C++) classes, anyway, so this shouldn't be an issue for them. [1] https://github.com/somzzz/druntime/blob/74882c8a48dd8a827181e3b89c4f0f205c881ac5/src/object.d#L50 |
September 10, 2017 Re: -betterC and extern(C++) classes | ||||
---|---|---|---|---|
| ||||
Posted in reply to Yuxuan Shui | By the way, can we dynamic_cast extern(C++) classes in C++? If not, what are we generating these TypeInfo_Class for? |
September 10, 2017 Re: -betterC and extern(C++) classes | ||||
---|---|---|---|---|
| ||||
Posted in reply to Moritz Maxeiner | On Sunday, 10 September 2017 at 14:42:42 UTC, Moritz Maxeiner wrote: > On Sunday, 10 September 2017 at 14:04:20 UTC, rikki cattermole wrote: >> On 10/09/2017 2:19 PM, Moritz Maxeiner wrote: >>> If TypeInfo for extern(C++) classes is removed, couldn't final extern(C++) classes without base class and which don't implement any interfaces omit the vtable so that the following assert holds: >>> >>> --- >>> final extern(C++) class Foo {} >>> static assert (__traits(classInstanceSize, Foo) == 0LU); >>> --- >>> >>> The reason I ask is that fairly often I have an abstraction that's better suited as a reference type than a value type, but doesn't need any runtime polymorphy (or the monitor standard classes have). Structs + pointers are the only way I know of to avoid the (in this special case) unneeded vtable overhead, but it always ends up looking worse to read. >> >> We can do it for any class if its final. > > Even final classes can always inherit (potentially already overridden) virtual methods from their parent classes and since all normal D classes inherit from core.object : Object [1], which defines virtual methods (`toString`, `toHash`, `opCmp, and `opEquals`), I don't see how this can be true. With a final class reference, we always know what function to call at compile time (since it can't be inherited). Therefore we don't need a vtable. > >> The problem isn't generating the vtable's. But the information required for casting. > > This applies to normal D classes, but D doesn't support (dynamic) casts for extern(C++) classes, anyway, so this shouldn't be an issue for them. > > [1] https://github.com/somzzz/druntime/blob/74882c8a48dd8a827181e3b89c4f0f205c881ac5/src/object.d#L50 |
September 10, 2017 Re: -betterC and extern(C++) classes | ||||
---|---|---|---|---|
| ||||
Posted in reply to Yuxuan Shui | On Sunday, 10 September 2017 at 15:12:12 UTC, Yuxuan Shui wrote:
> On Sunday, 10 September 2017 at 14:42:42 UTC, Moritz Maxeiner wrote:
>> On Sunday, 10 September 2017 at 14:04:20 UTC, rikki cattermole wrote:
>>> On 10/09/2017 2:19 PM, Moritz Maxeiner wrote:
>>>> If TypeInfo for extern(C++) classes is removed, couldn't final extern(C++) classes without base class and which don't implement any interfaces omit the vtable so that the following assert holds:
>>>>
>>>> ---
>>>> final extern(C++) class Foo {}
>>>> static assert (__traits(classInstanceSize, Foo) == 0LU);
>>>> ---
>>>>
>>>> The reason I ask is that fairly often I have an abstraction that's better suited as a reference type than a value type, but doesn't need any runtime polymorphy (or the monitor standard classes have). Structs + pointers are the only way I know of to avoid the (in this special case) unneeded vtable overhead, but it always ends up looking worse to read.
>>>
>>> We can do it for any class if its final.
>>
>> Even final classes can always inherit (potentially already overridden) virtual methods from their parent classes and since all normal D classes inherit from core.object : Object [1], which defines virtual methods (`toString`, `toHash`, `opCmp, and `opEquals`), I don't see how this can be true.
>
> With a final class reference, we always know what function to call at compile time (since it can't be inherited). Therefore we don't need a vtable.
---
class Base
{
string name()
{
return "Base";
}
}
class ChildA : Base
{
override string name()
{
return "ChildA";
}
}
final class ChildB : Base
{
override string name()
{
return "ChildB";
}
}
void foo(Base b)
{
import std.stdio;
b.name.writeln;
}
void main(string[] args)
{
Base b;
if (args.length > 1) b = new ChildA;
else b = new ChildB;
b.foo();
}
---
It is not known at compile time which class `foo`'s parameter `b` will actually be an instance of (Base, ChildA, or ChildB), so static dispatch is not possible; it requires dynamic dispatch. Since dynamic dispatch for classes is done in D via vtables, ChildB needs a vtable.
|
September 10, 2017 Re: -betterC and extern(C++) classes | ||||
---|---|---|---|---|
| ||||
Posted in reply to Yuxuan Shui | On Sunday, 10 September 2017 at 15:08:50 UTC, Yuxuan Shui wrote: > By the way, can we dynamic_cast extern(C++) classes in C++? It doesn't work for me OOTB with dmd 2.075, at least (though I may be missing something): --- classes.d --- import core.memory; extern(C++) class Parent { char id() { return 'P'; } } extern(C++) class Child : Parent { override char id() { return 'C'; } } extern(C++) Parent makeParent() { auto p = new Parent; GC.addRoot(cast(void*) p); return p; } extern(C++) Child makeChild() { auto c = new Child; GC.addRoot(cast(void*) c); return c; } extern(C++) void releaseParent(Parent p) { GC.removeRoot(cast(void*) p); } extern(C++) void releaseChild(Child c) { GC.removeRoot(cast(void*) c); } ----------------- --- main.cc --- #include <iostream> class Parent { public: virtual char id(); }; class Child : public Parent { }; extern Parent* makeParent(); extern Child* makeChild(); extern void releaseParent(Parent* p); extern void releaseChild(Child* c); extern "C" void rt_init(); extern "C" void rt_term(); bool isChild(Parent* p) { return nullptr != dynamic_cast<Child*>(p); } int main(int argc, char** argv) { rt_init(); Parent* p = makeParent(); Child* c = makeChild(); std::cout << p->id() << "\n"; std::cout << c->id() << "\n"; std::cout << "identifier\tChild\n"; std::cout << "p\t" << isChild(p) << "\t"; std::cout << "c\t" << isChild(c) << "\t"; releaseChild(c); releaseParent(p); rt_term(); return 0; } --------------- --- Compile&Link --- $ dmd -c classes.d $ g++ -std=c++11 -o main main.cc classes.o -L/path/to/dmd-2.075/lib64/ -lphobos2 /tmp/ccwjJ9Xe.o: In function `isChild(Parent*)': main.cc:(.text+0x20): undefined reference to `typeinfo for Parent' /tmp/ccwjJ9Xe.o:(.rodata._ZTI5Child[_ZTI5Child]+0x10): undefined reference to `typeinfo for Parent' collect2: error: ld returned 1 exit status -------------------- |
September 10, 2017 Re: -betterC and extern(C++) classes | ||||
---|---|---|---|---|
| ||||
Posted in reply to Yuxuan Shui | On 9/10/2017 7:01 AM, Yuxuan Shui wrote: > Is there a plan? Are there any simple tasks I can take/help? I filed an enhancement request: https://issues.dlang.org/show_bug.cgi?id=17822 The rest is kinda up to me. |
September 10, 2017 Re: -betterC and extern(C++) classes | ||||
---|---|---|---|---|
| ||||
Posted in reply to Yuxuan Shui | On 9/10/2017 8:08 AM, Yuxuan Shui wrote: > By the way, can we dynamic_cast extern(C++) classes in C++? No. Generally, one would need C++ RTTI for that to work, and that: 1. is specific to the particular C++ compiler 2. is undocumented, half-documented, or wrongly documented 3. requires the C++ runtime library to work It's certainly possible to do this, but requires time, effort, and a certain willingness to deal with the dirty underbelly of undocumented binary formats. > If not, what are we generating these TypeInfo_Class for? It has other uses, such as providing info for associative arrays and the garbage collector. |
Copyright © 1999-2021 by the D Language Foundation