digitalmars.D.learn - Use class template as a type
- dm (35/35) Nov 28 2016 Hi.
- rikki cattermole (7/7) Nov 28 2016 In your case I'd just swap out ``MyClass[] someArray;`` to ``Object[]
- dm (6/13) Nov 28 2016 I'm tried to use Object[], but got error
- rikki cattermole (6/18) Nov 28 2016 We have a handy dandy syntax for this:
- dm (2/8) Nov 28 2016 Hell yeah! It's works!
- Namespace (3/9) Nov 28 2016 Just out of interest: it looks like a dynamic_cast in C++ which
- rikki cattermole (3/14) Nov 28 2016 I wouldn't worry about it. You're already using classes and they are dog...
- Basile B. (5/16) Nov 28 2016 The cast from a class type to a sub class in itself does
- ag0aep6g (4/6) Nov 29 2016 That can't be right. A bad downcast gives you null, so it has to check
- Nicholas Wilson (8/43) Nov 28 2016 Thats because MyClass is a template class. Templates are note
- dm (31/37) Nov 28 2016 Maybe I must use some stub class or interface and override all
- Jerry (26/37) Nov 29 2016 To avoid having to use the Object class directly you can make an
Hi. Is it possible to write in D something like this? ``` abstract class MyClass(T) { public: property const(T) value(){return _value;} property void value(T val){_value = val;} ... private: T _value; ... } ... class MyClassFloat: MyClass!float ... class MyClassInt: MyClass!int ... void main() { MyClass[] someArray; someArray ~= new MyClassFloat(); ... someArray ~= new MyClassInt(); ... foreach(myClass; someArray) if(typeid(myClass) == typeid(MyClassInt)) myClass.value = 999; else myClass.value = 123.45f; ... } ``` When I trying to compile code like above I got Error: class MyClass(T) is used as a type.
Nov 28 2016
In your case I'd just swap out ``MyClass[] someArray;`` to ``Object[] someArray;``. But only because there are no members added without the extra typing in MyClass. Remember types in meta-programming in D are not erased, they exist in the assembly and are unique. Unlike Java who did the implementation rather wrong.
Nov 28 2016
On Monday, 28 November 2016 at 11:30:23 UTC, rikki cattermole wrote:In your case I'd just swap out ``MyClass[] someArray;`` to ``Object[] someArray;``. But only because there are no members added without the extra typing in MyClass. Remember types in meta-programming in D are not erased, they exist in the assembly and are unique. Unlike Java who did the implementation rather wrong.I'm tried to use Object[], but got error Error: no property 'value' for type 'object.Object' I guess I must cast() to MyClassInt or MyClassFloat, but how can I do it?
Nov 28 2016
On 29/11/2016 2:56 AM, dm wrote:On Monday, 28 November 2016 at 11:30:23 UTC, rikki cattermole wrote:We have a handy dandy syntax for this: if (MyClassInt subclass = cast(MyClassInt)value) { writeln(subclass.value); } If it doesn't cast to said type (it will be null) that branch won't execute.In your case I'd just swap out ``MyClass[] someArray;`` to ``Object[] someArray;``. But only because there are no members added without the extra typing in MyClass. Remember types in meta-programming in D are not erased, they exist in the assembly and are unique. Unlike Java who did the implementation rather wrong.I'm tried to use Object[], but got error Error: no property 'value' for type 'object.Object' I guess I must cast() to MyClassInt or MyClassFloat, but how can I do it?
Nov 28 2016
We have a handy dandy syntax for this: if (MyClassInt subclass = cast(MyClassInt)value) { writeln(subclass.value); } If it doesn't cast to said type (it will be null) that branch won't execute.Hell yeah! It's works! Thank you!
Nov 28 2016
We have a handy dandy syntax for this: if (MyClassInt subclass = cast(MyClassInt)value) { writeln(subclass.value); } If it doesn't cast to said type (it will be null) that branch won't execute.Just out of interest: it looks like a dynamic_cast in C++ which is considered as slow operation. Is that D cast also a dynamic cast and also slow? I've never used it, so I'm a bit curious.
Nov 28 2016
On 29/11/2016 3:35 AM, Namespace wrote:I wouldn't worry about it. You're already using classes and they are dog slow in general.We have a handy dandy syntax for this: if (MyClassInt subclass = cast(MyClassInt)value) { writeln(subclass.value); } If it doesn't cast to said type (it will be null) that branch won't execute.Just out of interest: it looks like a dynamic_cast in C++ which is considered as slow operation. Is that D cast also a dynamic cast and also slow? I've never used it, so I'm a bit curious.
Nov 28 2016
On Monday, 28 November 2016 at 14:35:36 UTC, Namespace wrote:The cast from a class type to a sub class in itself does absolutely nothing. It has only an effect when you call a virtual method. This is slow because of the indirection that happens when the right offset has to be found in the VTBL.We have a handy dandy syntax for this: if (MyClassInt subclass = cast(MyClassInt)value) { writeln(subclass.value); } If it doesn't cast to said type (it will be null) that branch won't execute.Just out of interest: it looks like a dynamic_cast in C++ which is considered as slow operation. Is that D cast also a dynamic cast and also slow? I've never used it, so I'm a bit curious.
Nov 28 2016
On 11/29/2016 02:21 AM, Basile B. wrote:The cast from a class type to a sub class in itself does absolutely nothing.That can't be right. A bad downcast gives you null, so it has to check the dynamic type information. Compare with upcasts which are statically known to be correct, so they don't need to check anything at runtime.
Nov 29 2016
On Tuesday, 29 November 2016 at 09:58:16 UTC, ag0aep6g wrote:On 11/29/2016 02:21 AM, Basile B. wrote:Usually casts to base classes can be determined if they're valid at compile-time. Take this for an example: class Foo { } class Bar : Foo { } void main() { auto bar = new Bar; auto foo = cast(Foo)bar; // The compiler should know that bar is of type Bar, which is a subclass of Foo and thus the cast theoretically is redundant. } Even in a situation like this, the compiler should be able to see if the cast could ever be invalid during compile-time determined by calls to fun. void fun(Cast)(Bar bar) { return cast(Cast)bar; // If Cast is Foo then the compiler should know the cast is redundant. ] I don't know if the D compiler actually takes such situation into account, but I'd assume it does some kind of optimization in regards of that.The cast from a class type to a sub class in itself does absolutely nothing.That can't be right. A bad downcast gives you null, so it has to check the dynamic type information. Compare with upcasts which are statically known to be correct, so they don't need to check anything at runtime.
Nov 30 2016
On 11/30/2016 10:42 AM, Bauss wrote:Usually casts to base classes can be determined if they're valid at compile-time.Yeah, that's what I said. A cast to a base class is an "upcast". Upcasts don't need run-time checks. The other direction (cast to more derived class) is a downcast. Downcasts need run-time checks.
Nov 30 2016
On Wednesday, 30 November 2016 at 14:53:21 UTC, ag0aep6g wrote:On 11/30/2016 10:42 AM, Bauss wrote:Actually I've always called an "upcast" a "downcast" ! This incredible misconception explains why you had to correct me after my yesterday's answer.Usually casts to base classes can be determined if they're valid at compile-time.Yeah, that's what I said. A cast to a base class is an "upcast". Upcasts don't need run-time checks. The other direction (cast to more derived class) is a downcast. Downcasts need run-time checks.
Nov 30 2016
On Monday, 28 November 2016 at 11:26:41 UTC, dm wrote:Hi. Is it possible to write in D something like this? ``` abstract class MyClass(T) { public: property const(T) value(){return _value;} property void value(T val){_value = val;} ... private: T _value; ... } ... class MyClassFloat: MyClass!float ... class MyClassInt: MyClass!int ... void main() { MyClass[] someArray;---^someArray ~= new MyClassFloat(); ... someArray ~= new MyClassInt(); ... foreach(myClass; someArray) if(typeid(myClass) == typeid(MyClassInt)) myClass.value = 999; else myClass.value = 123.45f; ... } ``` When I trying to compile code like above I got Error: class MyClass(T) is used as a type.Thats because MyClass is a template class. Templates are note types, instansiations of templates can be types. e.g. Myclass!float[] arr; // note this is not MyClass!(float[]); will work. As Rikki suggested using Object[] instead will allow use to store classes of different types.
Nov 28 2016
Thats because MyClass is a template class. Templates are note types, instansiations of templates can be types. e.g. Myclass!float[] arr; // note this is not MyClass!(float[]); will work. As Rikki suggested using Object[] instead will allow use to store classes of different types.Maybe I must use some stub class or interface and override all methods... But I so like D templates, as a result it's a small and easy to understand code. Or actually it's maybe a XY problem. I'm trying to implement OpenGL material manager and for OpenGL uniforms I tried to write: ``` abstract class Uniform(T) property ... property ... T _val;... void method()... ... class FloatUniform: Uniform!float ... override void method()... And in material class class Material ... Texture[] textures; Uniform[] uniforms; ... ``` Maybe i'm totally wrong and better just use glUniformXXX... in my main app instead of ``` auto uniform = new SomeTypeUniform... ... uniform.value = someValue; ``` ?
Nov 28 2016
On Monday, 28 November 2016 at 11:26:41 UTC, dm wrote:``` abstract class MyClass(T) { public: property const(T) value(){return _value;} property void value(T val){_value = val;} ... private: T _value; ... }To avoid having to use the Object class directly you can make an base class of the class template. Like: ``` abstract class MyClass {} abstract class MyClassImpl(T) { public: property const(T) value(){return _value;} property void value(T val){_value = val;} ... private: T _value; ... } MyClassInt and float inherits from MyClassImpl ``` And use it like: ``` void main() { MyClass[] objs; objs ~= new MyClassFloat(); objs ~= new MyClassInt(); } ```
Nov 29 2016
On Tuesday, 29 November 2016 at 15:56:23 UTC, Jerry wrote:abstract class MyClass {} abstract class MyClassImpl(T)Oops, forgot MyClassImpl should extend from MyClass. abstract class MyClassImpl(T) : MyClass { ... }
Nov 29 2016
On Tuesday, 29 November 2016 at 15:56:23 UTC, Jerry wrote:On Monday, 28 November 2016 at 11:26:41 UTC, dm wrote:I would rather go with an interface than a base class.``` abstract class MyClass(T) { public: property const(T) value(){return _value;} property void value(T val){_value = val;} ... private: T _value; ... }To avoid having to use the Object class directly you can make an base class of the class template. Like: ``` abstract class MyClass {} abstract class MyClassImpl(T) { public: property const(T) value(){return _value;} property void value(T val){_value = val;} ... private: T _value; ... } MyClassInt and float inherits from MyClassImpl ``` And use it like: ``` void main() { MyClass[] objs; objs ~= new MyClassFloat(); objs ~= new MyClassInt(); } ```
Nov 30 2016
On Tuesday, 29 November 2016 at 15:56:23 UTC, Jerry wrote:To avoid having to use the Object class directly you can make an base class of the class template. Like: ``` abstract class MyClass {} abstract class MyClassImpl(T) { public: property const(T) value(){return _value;} property void value(T val){_value = val;} ... private: T _value; ... } MyClassInt and float inherits from MyClassImpl ``` And use it like: ``` void main() { MyClass[] objs; objs ~= new MyClassFloat(); objs ~= new MyClassInt(); } ```Yes, but anyway you need to downcast if(MyClassBlahBlah subclass = cast(MyClassBlahBlah)obj)... So it's not much sense to have base class or interface MyClass.
Nov 30 2016