www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Class References

reply "Jeroen Bollen" <jbinero gmail.com> writes:
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
next sibling parent reply "John Colvin" <john.loughran.colvin gmail.com> writes:
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
next sibling parent "Maxim Fomin" <maxim maxim-fomin.ru> writes:
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:
 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.
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".
Oct 28 2013
prev sibling parent reply "Jeroen Bollen" <jbinero gmail.com> writes:
Is it possible to do something like:

TestInterface testi = new classReferenceList[integer];
Nov 18 2013
parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
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
parent reply "Jeroen Bollen" <jbinero gmail.com> writes:
On Monday, 18 November 2013 at 19:12:03 UTC, Ali Çehreli wrote:
 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
I was more looking for a way to just access a type/class by specifying an index... I don't really get your code.
Nov 20 2013
parent =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
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
prev sibling next sibling parent "Maxim Fomin" <maxim maxim-fomin.ru> writes:
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
prev sibling next sibling parent reply "Jared Miller" <none example.com> writes:
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
parent "Jared Miller" <none example.com> writes:
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
prev sibling parent "Baz" <burg.basile yahoo.fr> writes:
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 d/15303118#15303118 . 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