Compile-time variables

H. S. Teoh hsteoh at quickfur.ath.cx
Fri Apr 6 00:21:54 UTC 2018


On Thu, Apr 05, 2018 at 11:53:00PM +0000, Kayomn via Digitalmars-d-learn wrote:
[...]
> -------------------------------------------------------------------------------
> alias NodeTypeID = uint;
> 
> enum NodeTypeID getNodeID() {
> 	static NodeTypeID lastID = 0;
> 
> 	return lastID++;
> }
> 
> enum NodeTypeID getNodeID(T)() {
> 	static NodeTypeID typeID = getNodeID();
> 
> 	return typeID;
> }
> -------------------------------------------------------------------------------
> 
> The expectation is that this is executed at compile time,
[...]
> However, I've been struggling with an error pertaining to getNodeType.
> The return statement of lastID++ is flagging the error "Static
> variable cannot be read at compile time."

`lastID`, as declared above, are runtime variables. The 'static' in this
case just means it's thread-local, rather than allocated on the stack.
You cannot modify these variables at compile-time.


> I may just be taking too much of a C++ lens to this, but to me this
> seems like it should work? Am I missing a qualifier or something here?

You appear to be wanting to increment a global variable during
compile-time. Unfortunately, there is no such thing as a compile-time
global variable.  You will have to find some other way to implement what
you want.

One way to do this would be to use compile-time introspection to
construct a list of nodes, and then use a CTFE function or static
foreach to generate node IDs all at once.  For example:

	string generateEnum(T...)()
	{
		if (__ctfe) { // only run at compile-time
			string code = "enum NodeIds {";
			foreach (ident; T) {
				code ~= ident ~ ", ";
			}
			code ~= "}";
			return code;
		}
		else assert(0);
	}

	alias MyNodes = List!(
		// Just an example; you probably want to generate this
		// list via introspection, e.g. via __traits(getMembers)
		// or something like that.
		identifier1,
		identifier2,
		...
	);

	mixin(generateEnum!MyNodes); // defines `enum NodeIds`

	static assert(NodeIds.identifier1 == 0);
	static assert(NodeIds.identifier2 == 1);
	...

There are probably other ways to do it too, but I chose enum because it
naturally assigns incrementing IDs to its members, so it's a convenient
construct for this purpose.


T

-- 
Having a smoking section in a restaurant is like having a peeing section in a swimming pool. -- Edward Burr 


More information about the Digitalmars-d-learn mailing list