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?
Integral data types are data types that represent whole numbers. They are used to store data that cannot be fractional, such as counts or measurements. Integral data types are typically stored as 32-bit or 64-bit values.
The integral types are: char , signed char , unsigned char -8 bits. short int , signed short int , and unsigned short int -16 bits.
C# supports nine integral types: sbyte , byte , short , ushort , int , uint , long , ulong , and char . The integral types have the following sizes and ranges of values: The sbyte type represents signed 8-bit integers with values from -128 to 127 , inclusive.
Built-in types (also called fundamental types) are specified by the C++ language standard and are built into the compiler. Built-in types aren't defined in any header file. Built-in types are divided into three main categories: integral, floating-point, and void. Integral types represent whole numbers.
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);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With