2

I want to step through the members of a C++ struct and print out their values. I can easily code this explicitly, but is there any way of doing it without actually knowing what's in the struct?

I suppose I'm looking for a C++ equivalent of C#'s foreach command.

Thanks for any help.

ADD: I'm doing something like this in C#. This code sets the struct members from an XML file read previously:

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
private struct SettingsStruct
{
    public uint nLength;
}

private void UpdateSettings()
{
    SettingsStruct settings = new SettingsStruct();

    foreach (FieldInfo fieldInfo in typeof(SettingsStruct).GetFields())
    {
        string settingName = "SETTING." + fieldInfo.Name.ToUpper();
        if (appSettings.Contains(settingName))
        {
            switch (fieldInfo.FieldType.FullName)
            {
                case "System.UInt32":
                    fieldInfo.SetValueDirect(__makeref(settings), uint.Parse((string)appSettings[settingName]));
                    break;
            }
        }
    }
}
parsley72
  • 8,449
  • 8
  • 65
  • 98
  • 1
    you mean you can print the members of a C# Struct with a `foreach`? How? – default Jun 10 '11 at 10:00
  • possible duplicate of [Iterate Over Struct; Easily Display Struct Fields And Values In a RichEdit Box](http://stackoverflow.com/questions/1878285/iterate-over-struct-easily-display-struct-fields-and-values-in-a-richedit-box) – Kirill V. Lyadvinsky Jun 10 '11 at 10:35
  • You can use foreach and reflection to iterate over the members of an object in C#, but it's really a function of reflection not of foreach. – Ferruccio Jun 10 '11 at 12:18

6 Answers6

4

If you are willing to use boost fusion you can do this. First "promote" this structure to a fusion sequence, and then you can iterate through the sequence printing out each member.

Nim
  • 33,299
  • 2
  • 62
  • 101
2

You could overload operator<< for your struct, then you only have to write the code once.

fredoverflow
  • 256,549
  • 94
  • 388
  • 662
2

The following Stackoverflow answer should give you an idea on what you are looking for

Iterate Over Struct; Easily Display Struct Fields And Values In a RichEdit Box

Community
  • 1
  • 1
Ozair Kafray
  • 13,351
  • 8
  • 59
  • 84
1

Afraid not. C++ offers limited reflective capability. The RTTI C++ system gives you access to types, but no introspection to the fields within that type.

With some macro wizardry / hackery you might be able to achieve this, see Reflection for C++ for an example.

Jeff Foster
  • 43,770
  • 11
  • 86
  • 103
1

The foreach command does'nt do what you are saying in C#. The foreach iterates over the elements of a collection (array, set, list ...) not the members of a struct (say "length" ...).

The equivalent of foreach in C++ is to use iterators (xs.begin(), xs.end()). You can use BOOST_FOREACH to have a cleaner syntax (or for(X& s : xs) in C++1x).

ysdx
  • 8,889
  • 1
  • 38
  • 51
1

C++ doesn't allow iteration over general class members. However, if you are prepared to accept some limitations, and use techniques that some will regard as pure evil, you can set up a framework to allow iteration over members of a particular family of class types. This works by abusing the fact that the default assignment operator is recursively applied to all members of a class.

First we need to declare the types to include in the iteration:

struct Visitable1;
struct Visitable2;
struct Visitable3;

We also need an abstract base class for operations to do while iterating (destructor omitted for brevity; for safety, it should be either virtual or protected):

struct Visitor
{
    virtual void visit(Visitable1 &) = 0;
    virtual void visit(Visitable2 &) = 0;
    virtual void visit(Visitable3 &) = 0;

    static Visitor * current;
};

and a base class (using the "curiously recursive template" idiom) for the types we can include in the iteration; this is where the operator abuse happens, modifying the behaviour of self-assignment:

template <typename T>
struct Visitable
{
    void operator=(Visitable const & other)
    {
        if (&other == this) {
            Visitor::current->visit(static_cast<T&>(*this));
        }
    }
};

struct Visitable1 : Visitable<Visitable1> { /* some stuff */ };
struct Visitable2 : Visitable<Visitable2> { /* some stuff */ };
struct Visitable3 : Visitable<Visitable3> { /* some stuff */ };

Finally, we can define the iteration itself:

template <class T, class Visitor>
void for_each(T & t, Visitor v)
{
    Visitor::current = &v;
    t = t;
}

This does have some notable shortcomings:

  • The "visit" functions are virtual, and so can't be generic. I can't currently think of a way to allow the use of different Visitor classes without an abstract base class. As a consequence, the iteration can only be applied to a predeclared set of types.
  • The use of a static variable (Visitor::current) means that only one iteration can be in progress at any time, giving thread-safety and reentrancy issues. I can't currently think of a better way to pass state to operator=, since this only works when overloading the default operator=, with a single argument of the same type as the assignee.
  • You may be lynched if anyone catches you writing code like this.

See codepad.org for a demonstration.

Mike Seymour
  • 249,747
  • 28
  • 448
  • 644