I am trying to use the following code to get a list of integral data members from class:
import std.stdio;
import std.traits;
class D
{
static string[] integralMembers = getIntegralMembers();
static string[] getIntegralMembers()
{
auto allMembers = __traits(allMembers, D);
string[] tmp = new string[allMembers.length];
int ct = 0;
for(int i = 0; i != allMembers.length; ++i) {
bool isInteg = __traits(isIntegral, __traits(getMember, D, allMembers[i]));
if(isInteg) {
tmp[ct++] = allMembers[i];
}
}
string[] ret = new string[ct];
for(int i = 0; i != ct; ++i) {
ret[i] = tmp[i];
}
return ret;
}
int a;
this() { }
~this() { }
}
void main()
{
auto integralMembers = D.integralMembers;
foreach(mem; integralMembers)
{
writeln(mem);
}
}
But, compilation is failing with these errors:
main.d(17): Error: variable i cannot be read at compile time
main.d(17): Error: expression expected as second argument of __traits getMember
main.d(19): Error: variable i cannot be read at compile time
main.d(7): called from here: getIntegralMembers()
How do I make this code compile?
Even though the function will only run during compilation within that program, it must still be compilable as a function that can run at runtime.
You need to declare allMembers
as a manifest constant:
enum allMembers = __traits(allMembers, D);
allMembers
is a tuple. If you use auto
, it will be saved as a tuple of strings on the "stack", becoming a runtime value, thus inaccessible to compile-time evaluation for __traits
.
You need to use foreach
instead of for
. foreach
over a tuple is special in that it will unroll statically, thus the index (and value) will be accessible to __traits
.
Fixed program:
import std.stdio;
import std.traits;
class D
{
static string[] integralMembers = getIntegralMembers();
static string[] getIntegralMembers()
{
enum allMembers = __traits(allMembers, D);
string[] tmp = new string[allMembers.length];
int ct = 0;
foreach(i, member; allMembers) {
bool isInteg = __traits(isIntegral, __traits(getMember, D, member));
if(isInteg) {
tmp[ct++] = allMembers[i];
}
}
string[] ret = new string[ct];
for(int i = 0; i != ct; ++i) {
ret[i] = tmp[i];
}
return ret;
}
int a;
this() { }
~this() { }
}
void main()
{
auto integralMembers = D.integralMembers;
foreach(mem; integralMembers)
{
writeln(mem);
}
}