Thread overview
Checking for manifest constants
Mar 05, 2021
Bogdan
Mar 05, 2021
Basile B.
Mar 06, 2021
bogdan
March 05, 2021
I was using a trick with dmd to check for manifest constants which worked until dmd v2.094. Yesterday I tried it on the latest compiler and it failed with:


source/introspection/manifestConstant.d(37,28): Error: need this for name of type string
source/introspection/type.d(156,13): Error: value of this is not known at compile time

any ideas how to fix it? or, is it a bug with dmd?

```

/// Check if a member is manifest constant
bool isManifestConstant(T, string name)() {
  mixin(`return is(typeof(T.init.` ~ name ~ `)) && !is(typeof(&T.init.` ~ name ~ `));`);
}

/// ditto
bool isManifestConstant(alias T)() {
  return is(typeof(T)) && !is(typeof(&T));
}

enum globalConfig = 32;
int globalValue = 22;

unittest {
  struct Test {
    enum config = 3;
    int value = 2;
  }

  static assert(isManifestConstant!(Test.config));
  static assert(isManifestConstant!(Test, "config"));
  static assert(isManifestConstant!(globalConfig));

  static assert(!isManifestConstant!(Test.value));
  static assert(!isManifestConstant!(Test, "value"));
  static assert(!isManifestConstant!(globalValue));
}

void main() {}


```


March 05, 2021
On Friday, 5 March 2021 at 08:23:09 UTC, Bogdan wrote:
> I was using a trick with dmd to check for manifest constants which worked until dmd v2.094. Yesterday I tried it on the latest compiler and it failed with:
>
>
> source/introspection/manifestConstant.d(37,28): Error: need this for name of type string
> source/introspection/type.d(156,13): Error: value of this is not known at compile time
>
> any ideas how to fix it? or, is it a bug with dmd?
>
> ```
>
> /// Check if a member is manifest constant
> bool isManifestConstant(T, string name)() {
>   mixin(`return is(typeof(T.init.` ~ name ~ `)) && !is(typeof(&T.init.` ~ name ~ `));`);
> }
>
> /// ditto
> bool isManifestConstant(alias T)() {
>   return is(typeof(T)) && !is(typeof(&T));
> }
>
> enum globalConfig = 32;
> int globalValue = 22;
>
> unittest {
>   struct Test {
>     enum config = 3;
>     int value = 2;
>   }
>
>   static assert(isManifestConstant!(Test.config));
>   static assert(isManifestConstant!(Test, "config"));
>   static assert(isManifestConstant!(globalConfig));
>
>   static assert(!isManifestConstant!(Test.value));
>   static assert(!isManifestConstant!(Test, "value"));
>   static assert(!isManifestConstant!(globalValue));
> }
>
> void main() {}
>
>
> ```

Hello, you can use this template instead:

  template isManifestConstant(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 isManifestConstant = isKnown;
    else
        enum isManifestConstant = isKnown && is(typeof(V) == T[0]);
  }

The optional T is to verify if it is a compile time constant of a certain type.
the tests you wrote and that are not based on a string pass.

March 05, 2021
On Friday, 5 March 2021 at 08:23:09 UTC, Bogdan wrote:
> I was using a trick with dmd to check for manifest constants which worked until dmd v2.094. Yesterday I tried it on the latest compiler and it failed with:
>
>
> source/introspection/manifestConstant.d(37,28): Error: need this for name of type string
> source/introspection/type.d(156,13): Error: value of this is not known at compile time
>
> any ideas how to fix it? or, is it a bug with dmd?
>
> ```
>
> /// Check if a member is manifest constant
> bool isManifestConstant(T, string name)() {
>   mixin(`return is(typeof(T.init.` ~ name ~ `)) && !is(typeof(&T.init.` ~ name ~ `));`);
> }
>
> /// ditto
> bool isManifestConstant(alias T)() {
>   return is(typeof(T)) && !is(typeof(&T));
> }
>
> enum globalConfig = 32;
> int globalValue = 22;
>
> unittest {
>   struct Test {
>     enum config = 3;
>     int value = 2;
>   }
>
>   static assert(isManifestConstant!(Test.config));
>   static assert(isManifestConstant!(Test, "config"));
>   static assert(isManifestConstant!(globalConfig));
>
>   static assert(!isManifestConstant!(Test.value));
>   static assert(!isManifestConstant!(Test, "value"));
>   static assert(!isManifestConstant!(globalValue));
> }
>
> void main() {}
>
>
> ```

I suggest this:

    enum globalConfig = 32;
    int globalValue = 22;
    immutable globaImmutablelValue = 22;

    enum isManifestConstant(alias symbol) =
      __traits(compiles, { enum e = symbol; }) &&
      !__traits(compiles, { const ptr = &symbol; });

    unittest {
      struct Test {
        enum config = 3;
        int value = 2;
      }

      static assert(isManifestConstant!(Test.config));
      static assert(isManifestConstant!(mixin("Test.config")));

      static assert(isManifestConstant!(globalConfig));
      static assert(isManifestConstant!(mixin("globalConfig")));

      static assert(!isManifestConstant!(Test.value));
      static assert(!isManifestConstant!(mixin("Test.value")));

      static assert(!isManifestConstant!(globalValue));
      static assert(!isManifestConstant!(mixin("globalValue")));

      static assert(!isManifestConstant!(globaImmutablelValue));
      static assert(!isManifestConstant!(mixin("globaImmutablelValue")));
    }
March 06, 2021
On Friday, 5 March 2021 at 14:42:07 UTC, Petar Kirov [ZombineDev] wrote:
> On Friday, 5 March 2021 at 08:23:09 UTC, Bogdan wrote:
>> [...]
>
> I suggest this:
>
>     enum globalConfig = 32;
>     int globalValue = 22;
>     immutable globaImmutablelValue = 22;
>
>     enum isManifestConstant(alias symbol) =
>       __traits(compiles, { enum e = symbol; }) &&
>       !__traits(compiles, { const ptr = &symbol; });
>
>     unittest {
>       struct Test {
>         enum config = 3;
>         int value = 2;
>       }
>
>       static assert(isManifestConstant!(Test.config));
>       static assert(isManifestConstant!(mixin("Test.config")));
>
>       static assert(isManifestConstant!(globalConfig));
>       static assert(isManifestConstant!(mixin("globalConfig")));
>
>       static assert(!isManifestConstant!(Test.value));
>       static assert(!isManifestConstant!(mixin("Test.value")));
>
>       static assert(!isManifestConstant!(globalValue));
>       static assert(!isManifestConstant!(mixin("globalValue")));
>
>       static assert(!isManifestConstant!(globaImmutablelValue));
>       static assert(!isManifestConstant!(mixin("globaImmutablelValue")));
>     }

Thanks!

I ended using this:
```

/// Check if a member is manifest constant
enum isManifestConstant(T, string name) = isManifestConstant!(__traits(getMember, T, name));

/// ditto
enum isManifestConstant(alias symbol) = __traits(compiles, { enum e = symbol; }) &&
  !__traits(compiles, { const ptr = &symbol; });

```

It looks like mixin does not work well with protected/private members