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