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 

Reply via email to