Compile-time variables
Kayomn
spam at kayomn.net
Fri Apr 6 14:15:08 UTC 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?
More information about the Digitalmars-d-learn
mailing list