Jump to page: 1 2
Thread overview
Class References
Oct 28, 2013
Jeroen Bollen
Oct 28, 2013
John Colvin
Oct 28, 2013
Maxim Fomin
Nov 18, 2013
Jeroen Bollen
Nov 18, 2013
Ali Çehreli
Nov 20, 2013
Jeroen Bollen
Nov 20, 2013
Ali Çehreli
Oct 28, 2013
Maxim Fomin
Nov 20, 2013
Jared Miller
Nov 20, 2013
Jared Miller
Nov 22, 2013
Baz
October 28, 2013
Is it possible in D to create an enum of class references?
Something around the lines of:

enum ClassReferences : Interface {
    CLASS1 = &ClassOne,
    CLASS2 = &ClassTwo
}
October 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);
}
October 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
> }

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.
October 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:
>> 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".
November 18, 2013
Is it possible to do something like:

TestInterface testi = new classReferenceList[integer];
November 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

November 20, 2013
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.
November 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

November 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
> }

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();
}
November 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.
« First   ‹ Prev
1 2