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?