循环POD成员

Loop over POD members

本文关键字:成员 POD 循环      更新时间:2023-10-16

我想知道如何正确地循环一个普通旧数据类型的成员,以便获得关于它们的一些类型信息。即:

struct my_pod
{
    int a;
    double b;
};
template<typename POD>
void loopOverPOD()
{
    for_each(POD, member) // The magic part
    {
        // member::type should be for my_pod int, then double
        typename member::type i;
        // member::size_of should be equal to sizeof(int) then sizeof(double)
        // Trivial if we can have member::type information.
        int size = member::size_of;
        // member::offset_of should be equal to 0, then sizeof(int)
        // Trivial if we can have member::size_of information.
        int offset = member::offset_of;
    }
}

据我所知,在C++中,如果不使用模板进行一些棘手的操作,我们就无法进行简单的类型内省。但在这里,我找不到模板的具体解决方案,即使事实上使用了宏。问题更多的是关于我,而不是关于解决方案的存在。:-)

我不一定要求一个不会干扰的解决方案。

提前谢谢。

您可以使用boost.fusions ADAPT_STRUCT将POD转换为序列,然后使用fusions for_each将函数对象应用于每个成员。这是非侵入性的,您的POD类型将保持为POD。

好处是,您甚至可以将ADAPT_STRUCT宏放在一个与结构定义分离的(头-)文件中,并且只在需要迭代的代码中使用它们。

另一方面,这个宏需要重复提及成员的类型和名称。我想,在某个时候,融合将使用C++11特性来消除冗余(再次提及类型)。同时,可以创建一个宏来声明结构和ADAP_struct部分。

如果使用C++14及更新版本,则可以使用Boost.Precise and Flat Reflection(https://github.com/apolukhin/magic_get/)用于在POD和boost::typeindex::type_id_runtime(field)上循环打印类型:

#include <iostream>
#include <boost/pfr/precise.hpp>
#include <boost/pfr/flat.hpp>
#include <boost/type_index.hpp>
struct my_pod
{
    int a;
    double b;
};
struct my_struct
{
    char c;
    my_pod pod;
};
int main() {
    my_pod val{1, 2.5};
    my_struct var{'a', 1, 2.5};
    std::cout <<  "Flat:n";
    boost::pfr::flat_for_each_field(var, [](const auto& field, std::size_t idx) {
        std::cout << idx << ": " << boost::typeindex::type_id_runtime(field) << "; value: " << field << 'n';
    });
    std::cout <<  "nNot Flat:n";
    boost::pfr::for_each_field(var, [](const auto& field, std::size_t idx) {
        using namespace boost::pfr::ops;
        std::cout << idx << ": " << boost::typeindex::type_id_runtime(field) << "; value: " << field << 'n';
    });
}

此示例的输出:

Flat:
0: char; value: a
1: int; value: 1
2: double; value: 2.5
Not Flat:
0: char; value: a
1: my_pod; value: {1, 2.5}

虽然我不知道在这种情况下如何抵消。。。

C++没有可在结构成员中迭代的构造。

然而,存在一个标准类型std::tuple,您可以使用模板在编译时递归地迭代它的元素。