Is there any way to iterate through a struct?

Viewed 570

I would like to iterate through a struct which is defined in other library whose source is not under my control. So any lib which requires to define the struct with its own macros/adaptors like previous questions is not usable here. I found the closest way is using boost::hana. However, it still requires to fill up an adaptor before I can iterate through it. I attached an example here. I wonder is there any way I can automate the BOOST_HANA_ADAPT_STRUCT then I do not need to fill up all the struct member names in there (those structs in total have more than hundred members).

#include <iostream>
#include <boost/hana.hpp>
#include <typeinfo>
namespace hana=boost::hana;
struct adapt_test
{
    std::string name;
    int data;
};
BOOST_HANA_ADAPT_STRUCT(
    adapt_test
    , name
    , data
);
auto names = hana::transform(hana::accessors<adapt_test>(), hana::first);
int main() {
    hana::for_each(
        names, 
        [] (auto item)
        {
            std::cout << hana::to<char const *>(item) << std::endl;
        }
    );
    adapt_test s1{"a", 2};
    hana::for_each(
        s1, 
        [] (auto pair)
        {
        std::cout << hana::to<char const *>(hana::first(pair)) << "=" << hana::second(pair) << std::endl;
        }
    );
    return 0;
}

2 Answers

You can use Boost Flat Reflection like:

struct adapt_test
{
    std::string name;
    int data;
};
adapt_test s1{"a", 2};

std::cout << boost::pfr::get<0>(s1)  << std::endl;
std::cout << boost::pfr::get<1>(s1)  << std::endl;

boost::pfr::flat_for_each_field(s1, [] (const auto& field) { std::cout << field << std::endl; } );

P.S. Respect for @apolukhin for this library.

The basic answer to your question is no.

C++ does not treat identifiers as string literal (it could be indeed useful in some cases), and there is no bridge unfortunately between these kind of strings.

Hopefully, some standard one day will bring this ability, relieving us from having to go through macros or code generation, or maybe doing differently like this: telling "please treat my struct A { int x, y; } as a pair", where the meaning would be to match type of first and second to the members x and y and then building the types so that it works, it would be really useful for tuples as well. A kind of structured template matching.

Currently the best that can be done to my knowledge is to match structs to tuple without the names (as of C++17) because of the above limitation, such as with boost::hana or boost::fusion as you do.

Related