Iterate through Struct and Class Members
There are a couple of ways to do this, but you need to use some macros to either define or adapt the struct.
You can use the REFLECTABLE
macro given in this answer to define the struct like this:
struct A
{
REFLECTABLE
(
(int) a,
(int) b,
(int) c
)
};
And then you can iterate over the fields and print each value like this:
struct print_visitor
{
template<class FieldData>
void operator()(FieldData f)
{
std::cout << f.name() << "=" << f.get() << std::endl;
}
};
template<class T>
void print_fields(T & x)
{
visit_each(x, print_visitor());
}
A x;
print_fields(x);
Another way is to adapt the struct as a fusion sequence (see the documentation). Here's an example:
struct A
{
int a;
int b;
int c;
};
BOOST_FUSION_ADAPT_STRUCT
(
A,
(int, a)
(int, b)
(int, c)
)
Then you can print the fields as well using this:
struct print_visitor
{
template<class Index, class C>
void operator()(Index, C & c)
{
std::cout << boost::fusion::extension::struct_member_name<C, Index::value>::call()
<< "="
<< boost:::fusion::at<Index>(c)
<< std::endl;
}
};
template<class C>
void print_fields(C & c)
{
typedef boost::mpl::range_c<int,0, boost::fusion::result_of::size<C>::type::value> range;
boost::mpl::for_each<range>(boost::bind<void>(print_visitor(), boost::ref(c), _1));
}
Iterating through Struct members
You apply reflection in pretty much the same way as normal, using Type.GetFields
:
MyStruct structValue = new MyStruct(...);
foreach (var field in typeof(MyStruct).GetFields(BindingFlags.Instance |
BindingFlags.NonPublic |
BindingFlags.Public))
{
Console.WriteLine("{0} = {1}", field.Name, field.GetValue(structValue));
}
Note that if the struct exposes properties (as it almost certainly should) you could use Type.GetProperties
to get at those.
(As noted in comments, this may well not be a good thing to do in the first place, and in general I'm suspicious of user-defined structs, but I thought I'd include the actual answer anyway...)
EDIT: Now it seems you're interested in setting the fields, that's slightly more complicated due to the way value types work (and yes, this really shouldn't be a struct.) You'll want to box once, set values on the single boxed instance, and then unbox at the end:
object boxed = new MyStruct();
// Call FieldInfo.SetValue(boxed, newValue) etc
MyStruct unboxed = (MyStruct) boxed;
How to iterate through a struct's fields?
public struct GridNeighbours {
public enum Cardinal { North, East, South, West }
public static Vector2Int[] Neighbours = { new Vector2Int(0, 1), new Vector2Int(1, 0), new Vector2Int(0, -1), new Vector2Int(-1, 0) };
public Vector2Int this[Cardinal dirn] {
get { return this[(int)dirn]; }
set { this[(int)dirn] = value; }
}
public Vector2Int this[int dirn] {
get { return Neighbours[dirn]; }
set { Neighbours[dirn] = value; }
}
}
Example use:
var cell = new GridNeighbours();
var NorthNeighbour = cell[Cardinal.North];
Assert(cell[Cardinal.South] == cell[2]); // This is true!
===
Alternatively, if you want "direct" properties:
public struct GridNeighbours {
public enum Cardinal { North, East, South, West }
public static Vector2Int[] Neighbours = { new Vector2Int(0, 1), new Vector2Int(1, 0), new Vector2Int(0, -1), new Vector2Int(-1, 0) };
public static Vector2Int North { get { return Neighbours[0]; } set { Neighbours[0] = value; } }
public static Vector2Int East { get { return Neighbours[1]; } set { Neighbours[1] = value; } }
public static Vector2Int South { get { return Neighbours[2]; } set { Neighbours[2] = value; } }
public static Vector2Int West { get { return Neighbours[3]; } set { Neighbours[3] = value; } }
}
Iterate through struct by variable name
This may well be easier than you expect. First, some caveats:
Arrays are guaranteed, by the standard, to be contiguous; that is, there's no padding inserted between them, and the array itself is aligned with the alignment requirements of the element type.
Structs have no such restrictions; they can be subject to arbitrary padding. However, a given implementation (at a given version) will do this the same way in all translation units (otherwise, how else could the same structure definition be used to pass data across translation units?). The usual way this is done is fairly sane, especially when the struct contains only members of a single type. For such a struct, the alignment usually matches the largest alignment of the members, and there's usually no padding because all members have the same alignment.
In your case, your array of 1024 floats and your struct with 1024 float members almost certainly have exactly the same memory layout. This is absolutely not guaranteed by the standard, but your compiler may document its struct layout rules, and you can always assert the sizes and alignments match in your unit tests (you do have unit tests, right?)
Given those caveats, you will almost certainly be able to simply reinterpret_cast
(or memcpy
) between the two.
Related Topics
Using a Stl Map of Function Pointers
Does Vector::Erase() on a Vector of Object Pointers Destroy the Object Itself
Lifetime of a Std::Initializer_List Return Value
How Are Iterators and Pointers Related
Efficient 128-Bit Addition Using Carry Flag
C++ Handling Very Large Integers
Fast String Hashing Algorithm with Low Collision Rates with 32 Bit Integer
Difference Between Try-Catch Syntax for Function
The Simplest and Neatest C++11 Scopeguard
Is 'Long' Guaranteed to Be at Least 32 Bits
Weird Behavior of Right Shift Operator (1 >> 32)
Why Is a Boolean 1 Byte and Not 1 Bit of Size
What Expressions Yield a Reference Type When Decltype Is Applied to Them
Why Is Including "Using Namespace" into a Header File a Bad Idea in C++
C++ System() Not Working When There Are Spaces in Two Different Parameters