digitalmars.D.learn - Class References
- Jeroen Bollen (6/6) Oct 28 2013 Is it possible in D to create an enum of class references?
- John Colvin (25/31) Oct 28 2013 Short answer: No
- Maxim Fomin (32/44) Oct 28 2013 This is an arbitrary limitation imposed by Don and I disagree
- Jeroen Bollen (2/2) Nov 18 2013 Is it possible to do something like:
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (32/34) Nov 18 2013 We still don't know what the use case is :) but it is possible to store
- Jeroen Bollen (3/38) Nov 20 2013 I was more looking for a way to just access a type/class by
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (40/42) Nov 20 2013 TypeTuple can contain types. Do you know the index at compile time or at...
- Maxim Fomin (5/11) Oct 28 2013 You can define class references in module scope and initialize
- Jared Miller (28/34) Nov 20 2013 Here's my solution using an enum as you originally wanted.
- Jared Miller (3/7) Nov 20 2013 Oops, never mind - you don't need the "cast(string)" there.
- Baz (11/17) Nov 22 2013 at runtime make an array of *void and cast them according to a
Is it possible in D to create an enum of class references? Something around the lines of: enum ClassReferences : Interface { CLASS1 = &ClassOne, CLASS2 = &ClassTwo }
Oct 28 2013
On Monday, 28 October 2013 at 11:22:03 UTC, Jeroen Bollen wrote:Is it possible in D to create an enum of class references? Something around the lines of: enum ClassReferences : Interface { CLASS1 = &ClassOne, CLASS2 = &ClassTwo }Short answer: No Long answer: the enum values must be compile-time constants, that's what enums are all about. Addresses and references are not compile-time constants. What is the use case? There is probably a simple way of doing what you want. Why not: interface Interface{} class ClassOne : Interface {} class ClassTwo : Interface {} struct ClassReferences { Interface classOne, classTwo; } void main() { auto c1 = new ClassOne(); auto c2 = new ClassTwo(); /* either this*/ ClassReferences crs; crs.classOne = c1; crs.classtwo = c2; /* or this */ auto crs = ClassReferences(c1,c2); }
Oct 28 2013
On Monday, 28 October 2013 at 12:10:37 UTC, John Colvin wrote:On Monday, 28 October 2013 at 11:22:03 UTC, Jeroen Bollen wrote:This is an arbitrary limitation imposed by Don and I disagree with him. According to opinion you presented providing classes at CT requires having "addresses" but it can be viewed other way - providing classes at CT requires some valid value which should be preserved for using in RT. For example, nobody complains that having enumeration constant or module scope immutable qualified basic type int at CT requires to have some "address". Although int belongs to value type category, int as module variable has "address". Example to illustrate issue: enum E : int[] { A = [0,1] } immutable EI = [0,1]; enum EE = [0, 1]; void main() { E e1, e2; assert (e1 == e2 && e1 == [0,1]); e1[0] = 1; assert(e2[0] == 0); //EI[0] = 1; // Error: cannot modify immutable expression EI[0] assert(EI[0] == 0); // EE[0] = 1; // Error: constant [0, 1][0] is not an lvalue assert(EE[0] == 0); } Dynamic arrays like classes are "reference" types, so there are "addresses" involved. Not only this shows that CT references are possible, but that dmd can support similar behavior for classes. Replace int[] with some class and you will arrive that there is something wrong about idea that "enum values must be compile-time constants, addresses and references are not compile-time constants, thus reference types can't be compile-time expressions".Is it possible in D to create an enum of class references? Something around the lines of: enum ClassReferences : Interface { CLASS1 = &ClassOne, CLASS2 = &ClassTwo }Short answer: No Long answer: the enum values must be compile-time constants, that's what enums are all about. Addresses and references are not compile-time constants.
Oct 28 2013
Is it possible to do something like: TestInterface testi = new classReferenceList[integer];
Nov 18 2013
On 11/18/2013 10:28 AM, Jeroen Bollen wrote:Is it possible to do something like: TestInterface testi = new classReferenceList[integer];We still don't know what the use case is :) but it is possible to store types in a TypeTuple: import std.stdio; import std.typetuple; interface I {} class C1 : I {} class C2 : I {} I makeObject(T)() { return new T(); } I[] makeObjects(Ts...)() { I[] objects; foreach (T; Ts) { objects ~= makeObject!T(); } return objects; } void main() { alias typeList = TypeTuple!(C1, C2); auto objects = makeObjects!typeList(); writeln(objects); } The output: [deneme.C1, deneme.C2] Ali
Nov 18 2013
On Monday, 18 November 2013 at 19:12:03 UTC, Ali Çehreli wrote:On 11/18/2013 10:28 AM, Jeroen Bollen wrote:I was more looking for a way to just access a type/class by specifying an index... I don't really get your code.Is it possible to do something like: TestInterface testi = new classReferenceList[integer];We still don't know what the use case is :) but it is possible to store types in a TypeTuple: import std.stdio; import std.typetuple; interface I {} class C1 : I {} class C2 : I {} I makeObject(T)() { return new T(); } I[] makeObjects(Ts...)() { I[] objects; foreach (T; Ts) { objects ~= makeObject!T(); } return objects; } void main() { alias typeList = TypeTuple!(C1, C2); auto objects = makeObjects!typeList(); writeln(objects); } The output: [deneme.C1, deneme.C2] Ali
Nov 20 2013
On 11/20/2013 08:35 AM, Jeroen Bollen wrote:I was more looking for a way to just access a type/class by specifying an index... I don't really get your code.TypeTuple can contain types. Do you know the index at compile time or at run time? Here is a program that demonstrates constructing an object for both of those cases: module deneme; import std.stdio; import std.typetuple; import std.string; interface I {} class C1 : I {} class C2 : I {} // Question: Is there a way to determine the name of this module? string moduleName = "deneme"; static const typeNames = [ "C1", "C2" ]; void makeWithCompileTimeIndex(size_t index)() { alias typeList = TypeTuple!(C1, C2); alias Type = typeList[index]; auto o = new Type(); writefln("I made an object by using a compile-time index: %s", o); } void makeWithRunTimeIndex(size_t index) { string fullTypeName = format("%s.%s", moduleName, typeNames[index]); auto o = cast(I)Object.factory(fullTypeName); writefln("I made an object by using a run-time index: %s", o); } void main() { makeWithCompileTimeIndex!1(); writefln("I can make an object of these types: %s", typeNames); write("Please enter the index of the type that you want: "); size_t index; readf(" %s", &index); makeWithRunTimeIndex(index); } Ali
Nov 20 2013
On Monday, 28 October 2013 at 11:22:03 UTC, Jeroen Bollen wrote:Is it possible in D to create an enum of class references? Something around the lines of: enum ClassReferences : Interface { CLASS1 = &ClassOne, CLASS2 = &ClassTwo }You can define class references in module scope and initialize them in module constructor. This will not help if you want to have working classes in compile time, but may be useful in runtime.
Oct 28 2013
On Monday, 28 October 2013 at 11:22:03 UTC, Jeroen Bollen wrote:Is it possible in D to create an enum of class references? Something around the lines of: enum ClassReferences : Interface { CLASS1 = &ClassOne, CLASS2 = &ClassTwo }Here's my solution using an enum as you originally wanted. However, depending on what you're really trying to do, there could be a better way. import std.stdio; import std.traits : fullyQualifiedName; interface Foo { void bar(); } class Class1 : Foo { void bar() { writeln("Class1"); } } class Class2 : Foo { void bar() { writeln("Class2"); } } enum ClassNames : string { CLASS1 = fullyQualifiedName!Class1, CLASS2 = fullyQualifiedName!Class2 } Foo getObj(ClassNames name) { // without cast, it converts to the enum member name. return cast(Foo)Object.factory(cast(string)name); } void main() { auto c1 = getObj(ClassNames.CLASS1); auto c2 = getObj(ClassNames.CLASS2); assert(c1 && c2); c1.bar(); c2.bar(); }
Nov 20 2013
On Wednesday, 20 November 2013 at 23:06:37 UTC, Jared Miller wrote:Foo getObj(ClassNames name) { // without cast, it converts to the enum member name. return cast(Foo)Object.factory(cast(string)name); }Oops, never mind - you don't need the "cast(string)" there.
Nov 20 2013
On Monday, 28 October 2013 at 11:22:03 UTC, Jeroen Bollen wrote:Is it possible in D to create an enum of class references? Something around the lines of: enum ClassReferences : Interface { CLASS1 = &ClassOne, CLASS2 = &ClassTwo }at runtime make an array of *void and cast them according to a type tuple. at compile time, it's another philosophy: you gotta use TMP. Confere with http://stackoverflow.com/questions/15302514/are-there-metaclasses-or-class-reference-in . Because the reference to a class type (it's a compile-time stuff) can be interpreted by using template meta programming (also a compile-time stuff).It's just another language philosophy but the result at the run-time is the same (about this case).
Nov 22 2013