April 06, 2018
On Friday, 6 April 2018 at 02:20:29 UTC, Kayomn wrote:
>
> Wrong example code, here's the correct example:
> --------------------------------------------------------------------------------
> switch (queryString(childJson,"type")) {
> 	case (typeof (Sprite).name):
> 		child = this.addChild!(Sprite)(childName);
>
> 		break;
>
> 	case (typeof (Camera).name):
> 		child = this.addChild!(Camera)(childName);
>
> 		break;
>
>  	default:
>  		child = this.addChild!(Node)(childName);
>
> 		break;
> }
> --------------------------------------------------------------------------------

Hi, could you show a bit more implementation details in the C++ version that works? Maybe someone can translate that to the appropriate D version?

The problem seems to be that switching on a runtime value and pattern matching with a compile time value is hard to pull off automatically without some sort of bridge (or of course I've misunderstood this exercise)

So if you had:

class R {
  string type() { return R.stringof; }
}
class A: R {
  override string type() { return A.stringof; }
}
class B: R {
  override string type() { return B.stringof; }
}

string type(T: R)() {
    return T.stringof;
}

void main() {
  R node = new A;
  final switch (node.type) {
  case type!R: writeln("R"); break;
  case type!A: writeln("A"); break;
  case type!B: writeln("B"); break;
  }
}

(maybe not a good idea to use stringof though, typeid probably better)

Cheers
April 06, 2018
>
> Besides this, I tried something with types used as user defined attributes.
> https://dlang.org/spec/attribute.html#uda
>
> Automatic compile time tagging is not my speciality, however, I think is also achievable with mixins somehow?
> But I don't know how to workaround the bug
> https://issues.dlang.org/show_bug.cgi?id=18718
> at this moment...
>
> https://run.dlang.io/is/DmBhO5

> Does the default case handle an unspecified class or does it handle a class which is specified, but is not mentioned in any of previous cases?

So in this example code the switch table is being used for loading data serialized into text. If the class cannot determine the node ID or it uses the default node type ID (e.g. the Node type if super "Node") it will create a simple node, as you can always be sure no matter what the type there will be sufficient information stored in the data to construct a default Node.

> Another information shortage is: are the tags exclusive or not? So, is it possible that a class has more then one tag (still being unique (tuple))?

ID tags are unique and spsecific to the class type. There shouldn't be more than one type ID assigned to one class type.

The idea behind what it is I am doing is I am implementing a solution to getting a type index, similar to std.variant.Variant.type(). The way that I implemented this in C++ is like so:

--------------------------------------------------------------------------------
inline unsigned int getNodeTypeID() {
    static unsigned int lastID = 0;

    return lastID++;
}

template<typename T> inline unsigned int getNodeTypeID() {
    static unsigned int typeID = getNodeTypeID();

    return typeID;
}
--------------------------------------------------------------------------------

In this C++ example I am exploiting the fact that templates are generated at compile-time to execute getNodeTypeID for each new type instance generated. After initial type generation, whenever they are called at runtime they were return the ID assigned to that function template instance that was generated at compile-time.

It's pretty simple, and to be honest I'm surprised this has been causing me such a headache implementing it in D.
April 06, 2018
On Friday, 6 April 2018 at 13:10:23 UTC, Kayomn wrote:
> ID tags are unique and spsecific to the class type. There shouldn't be more than one type ID assigned to one class type.
>
> The idea behind what it is I am doing is I am implementing a solution to getting a type index, similar to std.variant.Variant.type(). The way that I implemented this in C++ is like so:
>
> --------------------------------------------------------------------------------
> inline unsigned int getNodeTypeID() {
>     static unsigned int lastID = 0;
>
>     return lastID++;
> }
>
> template<typename T> inline unsigned int getNodeTypeID() {
>     static unsigned int typeID = getNodeTypeID();
>
>     return typeID;
> }
> --------------------------------------------------------------------------------
>
> In this C++ example I am exploiting the fact that templates are generated at compile-time to execute getNodeTypeID for each new type instance generated. After initial type generation, whenever they are called at runtime they were return the ID assigned to that function template instance that was generated at compile-time.
>
> It's pretty simple, and to be honest I'm surprised this has been causing me such a headache implementing it in D.

That's because the C++ code doesn't do what you think it does. Apparently you think that getNodeID() is executed at compile time. This is not the case, which you can verify by adding "constexpr" to it:

$ g++ -std=c++14 -Wall -Wextra -c -o example example.cpp
main.cpp: In function ‘constexpr unsigned int getNodeTypeID()’:
main.cpp:2:25: error: ‘lastID’ declared ‘static’ in ‘constexpr’ function
     static unsigned int lastID = 0;

In fact, you're "exploiting" the fact that static variables in C++ can be initialized at runtime (which is probably not what you want).
The equivalent D code is:

uint newID()
{
    static uint lastID;

    return lastID++;
}

uint getNodeID(T)()
{
    static bool inited;
    static uint id;

    if (!inited)
    {
        id = newID();
        inited = true;
    }

    return id;
}

(yes, C++ does insert some hidden bool that tells it whether the variable was initialized or not).
Naturally, you can't use that for constructing switches or other compile time constructs.
April 06, 2018
On Friday, 6 April 2018 at 13:55:55 UTC, nkm1 wrote:
> On Friday, 6 April 2018 at 13:10:23 UTC, Kayomn wrote:
>> ID tags are unique and spsecific to the class type. There shouldn't be more than one type ID assigned to one class type.
>>
>> The idea behind what it is I am doing is I am implementing a solution to getting a type index, similar to std.variant.Variant.type(). The way that I implemented this in C++ is like so:
>>
>> --------------------------------------------------------------------------------
>> inline unsigned int getNodeTypeID() {
>>     static unsigned int lastID = 0;
>>
>>     return lastID++;
>> }
>>
>> template<typename T> inline unsigned int getNodeTypeID() {
>>     static unsigned int typeID = getNodeTypeID();
>>
>>     return typeID;
>> }
>> --------------------------------------------------------------------------------
>>
>> In this C++ example I am exploiting the fact that templates are generated at compile-time to execute getNodeTypeID for each new type instance generated. After initial type generation, whenever they are called at runtime they were return the ID assigned to that function template instance that was generated at compile-time.
>>
>> It's pretty simple, and to be honest I'm surprised this has been causing me such a headache implementing it in D.
>
> That's because the C++ code doesn't do what you think it does. Apparently you think that getNodeID() is executed at compile time. This is not the case, which you can verify by adding "constexpr" to it:
>
> $ g++ -std=c++14 -Wall -Wextra -c -o example example.cpp
> main.cpp: In function ‘constexpr unsigned int getNodeTypeID()’:
> main.cpp:2:25: error: ‘lastID’ declared ‘static’ in ‘constexpr’ function
>      static unsigned int lastID = 0;
>
> In fact, you're "exploiting" the fact that static variables in C++ can be initialized at runtime (which is probably not what you want).
> The equivalent D code is:
>
> uint newID()
> {
>     static uint lastID;
>
>     return lastID++;
> }
>
> uint getNodeID(T)()
> {
>     static bool inited;
>     static uint id;
>
>     if (!inited)
>     {
>         id = newID();
>         inited = true;
>     }
>
>     return id;
> }
>
> (yes, C++ does insert some hidden bool that tells it whether the variable was initialized or not).
> Naturally, you can't use that for constructing switches or other compile time constructs.

Figured I had a handle on how it worked doing but guess not. One final question, however.

I've implemented this test bed with your example to what I think is your exact implementation, but it seems to be giving unexpected output.

--------------------------------------------------------------------------------
import std.stdio;

uint newID() {
	static uint lastID;

	return lastID;
}

uint getNodeID(T)() {
	static bool inited;
	static uint id;

	if (!inited) {
		id = newID();
		inited = true;
	}
	return id;
}

class Node {}

class Sprite {}

class Camera {}

void main() {
	// Test 01.
	writeln("Test 01.");
	writeln(getNodeID!(Node)(),'\t',getNodeID!(Sprite)(),'\t',getNodeID!(Camera)());
	// Test 02.
	writeln("Test 02.");
	writeln(getNodeID!(Node)(),'\t',getNodeID!(Sprite)(),'\t',getNodeID!(Camera)());
}
--------------------------------------------------------------------------------

Output:
--------------------------------------------------------------------------------
Performing "debug" build using gdc for x86_64.
dlangtest ~master: building configuration "application"...
Running ./dlangtest
Test 01.
0	0	0
Test 02.
0	0	0
--------------------------------------------------------------------------------

Have I misunderstood something?
April 06, 2018
On Friday, 6 April 2018 at 14:15:08 UTC, Kayomn wrote:
> On Friday, 6 April 2018 at 13:55:55 UTC, nkm1 wrote:
>> [...]
>
> Figured I had a handle on how it worked doing but guess not. One final question, however.
>
> [...]

Nevermind, I'm blind. I missed the post-increment in newID().
1 2
Next ›   Last »