1 import phobos.sys.meta : AliasSeq; 2 3 struct S 4 { 5 int x; 6 float y; 7 } 8 static assert(FieldNames!S == AliasSeq!("x", "y")); 9 10 // Since the AliasSeq contains values, all of which are of the same type, 11 // it can be used to create a dynamic array, which would be more 12 // efficient than operating on an AliasSeq in the cases where an 13 // AliasSeq is not necessary. 14 static assert([FieldNames!S] == ["x", "y"]); 15 16 class C 17 { 18 // static variables are not included. 19 static int var; 20 21 // Manifest constants are not included. 22 enum lang = "dlang"; 23 24 // Functions are not included, even if they're @property functions. 25 @property int foo() { return 42; } 26 27 string s; 28 int i; 29 int[] arr; 30 } 31 static assert(FieldNames!C == AliasSeq!("s", "i", "arr")); 32 33 static assert([FieldNames!C] == ["s", "i", "arr"]); 34 35 // Only direct member variables are included. Member variables from any base 36 // classes are not. 37 class D : C 38 { 39 real r; 40 } 41 static assert(FieldNames!D == AliasSeq!"r"); 42 43 static assert([FieldNames!D] == ["r"]); 44 45 // FieldNames will always be empty for an interface, since it's not legal 46 // for interfaces to have member variables. 47 interface I 48 { 49 } 50 static assert(FieldNames!I.length == 0); 51 52 union U 53 { 54 int i; 55 double d; 56 long l; 57 S s; 58 } 59 static assert(FieldNames!U == AliasSeq!("i", "d", "l", "s")); 60 61 static assert([FieldNames!U] == ["i", "d", "l", "s"]);; 62 63 // FieldNames only operates on aggregate types. 64 static assert(!__traits(compiles, FieldNames!int)); 65 static assert(!__traits(compiles, FieldNames!(S*))); 66 static assert(!__traits(compiles, FieldNames!(C[])));
Evaluates to an AliasSeq of the names (as strings) of the member variables of an aggregate type (i.e. a struct, class, interface, or union).
These are fields which take up memory space within an instance of the type (i.e. not enums / manifest constants, since they don't take up memory space, and not static member variables, since they don't take up memory space within an instance).
Hidden fields (like the virtual function table pointer or the context pointer for nested types) are not included.
For classes, only the direct member variables are included and not those of any base classes.
For interfaces, the result of FieldNames is always empty, because interfaces cannot have member variables. However, because interfaces are aggregate types, they work with FieldNames for consistency so that code that's written to work on aggregate types doesn't have to worry about whether it's dealing with an interface.