Thread overview
Detecting manifest contants
Mar 12, 2022
Anonymouse
Mar 12, 2022
Paul Backus
Mar 12, 2022
Paul Backus
Mar 12, 2022
Anonymouse
Mar 13, 2022
Basile B.
March 12, 2022

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.

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?

March 12, 2022

On Saturday, 12 March 2022 at 18:49:32 UTC, Anonymouse wrote:

>

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.

It sounds like what you want here is .tupleo.

March 12, 2022

On Saturday, 12 March 2022 at 19:00:23 UTC, Paul Backus wrote:

>

On Saturday, 12 March 2022 at 18:49:32 UTC, Anonymouse wrote:

>

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.

It sounds like what you want here is .tupleo.

Typo: .tupleof

March 12, 2022

On Saturday, 12 March 2022 at 19:01:06 UTC, Paul Backus wrote:

>

Typo: .tupleof

I use .tupleof otherwise, but this is old stuff from when I didn't know of it. I'll have to refactor it some day, I had hoped for it to be just... not yet.

March 13, 2022

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.

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.

/**
 * 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;
}