3

I remembered that C++20 got features to iterate over members in a struct ,I read a blog about it with example codes, but I can't find it anymore.

For example:

struct Foo {
  std::string a;
  std::string b;
  std::string c;
}; 


struct Bar {
  std::string e;
  std::string f;
};

template <typename T>
void PrintMember (T& t) {
  // what to do to iterate members in C++ 20?
}

The code of the template may not look like that, since C++20 got concepts. Any idea how to write codes to iterate members in Foo and Bar?

P.S. I remembered that it use concepts to do the trick, but maybe I'm wrong or the blog is wrong (that's why I can't find it anymore), an answer of "No you can't, even in C++20" is welcomed.

P.P.S. One thing I didn't clarify, I don't need the field name, but I need to iterate for all fields, including inherited fields.

psionic12
  • 185
  • 1
  • 11
  • is this what you are asking about? https://github.com/boostorg/pfr – NoSenseEtAl Apr 19 '21 at 10:17
  • dupe of [Iterating over a struct in C++](https://stackoverflow.com/questions/17660095/iterating-over-a-struct-in-c) and others – underscore_d Apr 19 '21 at 10:58
  • There are some libraries and there is an effort to make this a feature, but it's still not available sadly. We have to wait. I'd love to have this too, it would save a lot of braindead coding, where all you do is pair struct member names with their values manually. – Tomáš Zato Apr 19 '21 at 11:22

2 Answers2

4

(Here I assume you would like to get the field name as well)

To realize this without tricks (e.g. additional tools or manual additions of meta information) you need the C++ reflection capability.

Even though it is available as a technical specification, this is not (yet) part of C++ (with C++20 being the latest standard to-date).

Andreas H.
  • 5,557
  • 23
  • 32
  • Thanks for answering, I remembered that the blog use concepts to do the trick, but it may wrong, that's why I can't find it anymore. I'll take this as accepted answer if no one else answered. – psionic12 Apr 19 '21 at 09:53
  • To be more precise: This answer only applies if you need access to the name of the field. If you do not need the name, just reference fields by index, this can be done in C++17. Essentially it is an application of structured bindings. – Andreas H. Apr 19 '21 at 10:40
  • No, I don't need the field name, just calling methods on fields, could you explain more about how to use C++17 to accomplish this? – psionic12 Apr 21 '21 at 04:05
  • With structured bindings in C++17 one can unpack any struct: e.g. for struct with three members: `auto & [a,b,c] = struct_val;` The number of members can be detected sort of automatically when one has a lot of structured bindings with different number of variables. But there is no need to implement all the missing boilerplate code to access a certain member by index. It is implemented for instance by the PFR library (as given by the other answer). Essentially it gives access to any struct as unnamed tuple. If one needs field names we have to wait for reflection. – Andreas H. Apr 21 '21 at 05:19
  • It’s not going to become part of C++ **20** in the future… – Davis Herring Apr 21 '21 at 08:52
2

You can use the Boost PFR library. To print members of a struct you can simply use the built-in boost::pfr::io utility: (godbolt)

template <typename T>
void PrintMember (const T& t) {
    std::cout << boost::pfr::io(t);
}

To be more general, you can use boost::pfr::for_each_field: (godbolt)

template <typename T>
void PrintMember (const T& t) {
    boost::pfr::for_each_field(t, [](auto&& x){
        std::cout << x << ' ';
    });
}

Both solutions work in C++17.

Regarding printing member field names. I'm afraid it's not possible currently without explicitly specifying them. If you're fine with that, you can try using a C++ reflection library until reflection is integrated into the standard.

janekb04
  • 4,304
  • 2
  • 20
  • 51
  • True, but it will not print the field name, just the value. (even though the OP did not specify whether he/she would like to have field names included or not) – Andreas H. Apr 19 '21 at 10:58
  • @AndreasH. I updated the answer with references to reflection libraries that allow to print member names. – janekb04 Apr 19 '21 at 11:40
  • Hi, it seems that inherited classes are not supported, but thanks for giving a solution. – psionic12 Apr 21 '21 at 04:11
  • @psionic12 If this answer or Andreas H.'s answer solved your problem, you can mark one answer as accepted by using the checkmark: https://stackoverflow.com/help/someone-answers . – janekb04 Apr 23 '21 at 09:46