On Saturday, 12 March 2022 at 18:49:32 UTC, Anonymouse wrote:
I'm introspecting structs, and I ran into an issue where `__traits(derivedMembers)` includes manifest constant enums in the returned tuple.

What is the correct way to statically detect these? The immediate thing that springs to mind is `is(symbol == enum)`, but it's not it.

Currently I'm testing if a function that takes the address of the member compiles, and I think it works, but like with everything `__traits(compiles)` it strikes me as it might not be the right way to go about things.

```d
struct Foo
{
    int i;
    enum k = 42;
}

void main()
{
    foreach (memberstring; __traits(derivedMembers, Foo))
    {
static if (__traits(compiles, { Foo f; auto ptr = &__traits(getMember, f, memberstring); }))
        {
            // ...
        }
    }
}
```

What else can I try?

A way is to try declaring an enum with the value returned by the `getMember` trait.

```d
/**
 * Indicates wether something is a value known at compile time.
 *
 * Params:
 *      V = The value to test.
 *      T = Optional, the expected value type.
 */
template isCompileTimeValue(alias V, T...)
if (T.length == 0 || (T.length == 1 && is(T[0])))
{
    enum isKnown = is(typeof((){enum v = V;}));
    static if (!T.length)
        enum isCompileTimeValue = isKnown;
    else
enum isCompileTimeValue = isKnown && is(typeof(V) == T[0]);
}
///
unittest
{
    string a;
    enum b = "0";
    enum c = 0;
    static assert(!isCompileTimeValue!a);
    static assert(isCompileTimeValue!b);
    static assert(isCompileTimeValue!c);
    static assert(isCompileTimeValue!(b,string));
    static assert(isCompileTimeValue!(c,int));
    static assert(!isCompileTimeValue!(c,char));
    static assert(!isCompileTimeValue!(char));
}

/// ditto
template isCompileTimeValue(V, T...)
if (T.length == 0 || (T.length == 1 && is(T[0])))
{
    enum isCompileTimeValue = false;
}
```

Reply via email to