www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Checking for manifest constants

reply Bogdan <szabobogdan yahoo.com> writes:
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() {}


```
Mar 05 2021
next sibling parent Basile B. <b2.temp gmx.com> writes:
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.
Mar 05 2021
prev sibling parent reply Petar Kirov [ZombineDev] <petar.p.kirov gmail.com> writes:
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"))); }
Mar 05 2021
parent bogdan <szabobogdan3 gmail.com> writes:
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
Mar 06 2021