在 C++ 中迭代结构

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/17660095/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 21:19:47  来源:igfitidea点击:

Iterating over a struct in C++

c++struct

提问by msd_2

I have a structure

我有一个结构

typedef struct A
{
    int a;
    int b;
    char * c;
}aA;

I want to iterate over each an every member of the structure and print its value. Something like:

我想遍历结构的每个成员并打印其值。就像是:

void print_struct_value(struct *A)
{
    for each member of struct A
    cout << "struct name . member name" << "value";
}

How can this be done in C++ ??

这怎么能在 C++ 中完成?

回答by sehe

Perhaps you can string something together using Boost Fusion/Phoenix:

也许您可以使用 Boost Fusion/Phoenix 将一些东西串在一起:

See it live on Coliru!

Coliru直播

#include <boost/fusion/adapted/struct.hpp>
#include <boost/fusion/include/for_each.hpp>
#include <boost/phoenix/phoenix.hpp>
using boost::phoenix::arg_names::arg1;

#include <string>
#include <iostream>

struct A
{
    int a;
    int b;
    std::string c;
};

BOOST_FUSION_ADAPT_STRUCT(A, (int,a)(int,b)(std::string,c));

int main()
{
    const A obj = { 1, 42, "The Answer To LtUaE" };

    boost::fusion::for_each(obj, std::cout << arg1 << "\n");
}

Update: Recent versions of boost can use C++11 type deduction:

BOOST_FUSION_ADAPT_STRUCT(A,a,b,c);

更新:boost 的最新版本可以使用 C++11 类型推导:

BOOST_FUSION_ADAPT_STRUCT(A,a,b,c);

Output:

输出:

1
42
The Answer To LtUaE

回答by 0x499602D2

You can't iterate over an object's data members. You can use std::ostream's stream insertion operator to print individually however:

您不能遍历对象的数据成员。您可以使用std::ostream的流插入运算符单独打印:

struct A
{
    int a;
    int b;
    std::string c;

    friend std::ostream& operator <<(std::ostream& os, A const& a)
    {
        return os << a.a << '\n'
                  << a.b << '\n'
                  << a.c << '\n';
    }
};

And inside main:

内部主要:

int main()
{
    A a = {5, 10, "apple sauce"};

    std::cout << a;
}

Output:

输出:

5
10
apple sauce

5
10
苹果酱

Here is a demo.

这是一个演示。

回答by Paul Fultz II

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 REFLECTABLEmacro given in this answerto define the struct like this:

您可以使用此答案中REFLECTABLE给出的宏来定义结构,如下所示:

struct A
{
    REFLECTABLE
    (
        (int) a,
        (int) b,
        (const char *) 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;
    const char * c;
};

BOOST_FUSION_ADAPT_STRUCT
(
    A,
    (int, a)
    (int, b)
    (const char *, 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(), _1, boost::ref(c)));
}

回答by small_duck

C++ does not support reflection out of the box, so what you are asking for is impossible within the core language.

C++ 不支持开箱即用的反射,因此您所要求的在核心语言中是不可能的。

Various libraries try to provide such functionality, typically by making you register your fields through some methods or macros, which will behind the scene save them into a collection of some sort, on which you can iterate.

各种库都试图提供这样的功能,通常是通过一些方法或宏让您注册您的字段,这将在幕后将它们保存到某种集合中,您可以对其进行迭代。

回答by Filip Roséen - refp

can I iterate over the members of a struct in standard c++?

我可以在标准 C++ 中迭代结构的成员吗?

No, standard c++doesn't provide a method for accomplishing what you are asking for, you "iterate" elements of a container - you cannot iterate over members of a certain type.

不,标准C++没有提供一种方法来完成您的要求,您“迭代”容器的元素 - 您不能迭代某种类型的成员。

"reflection" (as this type of feature is most often referred to isn't part of C++).

反射”(因为这种类型的特性最常被提及,它不是 C++ 的一部分)。



in c++11you could use a std::tuple<int,int,char*>instead of your struct A, it will store the same kind of elements and is far easier to iterate over (using some templatemagic).

c++11 中,您可以使用 astd::tuple<int,int,char*>代替您的struct A,它将存储相同类型的元素并且更容易迭代(使用一些模板魔术)。

the elements won't have names ranging from 'a'to 'c'but if you'd like to print it that way this of course can be accomplished by some extra lines of code.

元素的名称不会从'a'到,'c'但如果您想以这种方式打印它,当然可以通过一些额外的代码行来完成。

To access a specific element you'll use std::get<N> (your_tuple)where Nis a integral ranging from 0 to std::tuple_size<std::tuple<int,int,char*>>::value - 1(ie. 2).

要访问特定元素,您将使用std::get<N> (your_tuple)whereN是从 0 到std::tuple_size<std::tuple<int,int,char*>>::value - 1(即 2)的整数。



回答by daminetreg

As suggested by @Paul I use BOOST_FUSION_ADAPT_STRUCT with a self written for_each_member function :

正如@Paul 所建议的那样,我将 BOOST_FUSION_ADAPT_STRUCT 与自己编写的 for_each_member 函数一起使用:

/**
 * \brief Allows iteration on member name and values of a Fusion adapted struct.
 * 
 *  
 * BOOST_FUSION_ADAPT_STRUCT(ns::point,
 *      (int, x)
 *      (int, y)
 *      (int, z));
 *
 * template<class T>
 * print_name_and_value(const char* name, T& value) const {
 *    std::cout << name << "=" << value << std::endl;
 * } 
 *
 * 
 * int main(void) {
 *  
 *  ns::point mypoint;
 *
 *  
 *      boost::fusion::for_each_member(mypoint, &print_name_and_value);
 *
 *
 * }
 *
 */
#ifndef BOOST_FUSION_FOR_EACH_MEMBER_HPP
#define BOOST_FUSION_FOR_EACH_MEMBER_HPP

#include <functional>

#include <boost/fusion/include/adapt_struct.hpp>

#include <boost/fusion/sequence/intrinsic/begin.hpp>
#include <boost/fusion/sequence/intrinsic/end.hpp>
#include <boost/fusion/sequence/intrinsic/front.hpp>
#include <boost/fusion/iterator/equal_to.hpp>
#include <boost/fusion/iterator/next.hpp>
#include <boost/fusion/iterator/deref.hpp>
#include <boost/fusion/iterator/distance.hpp>
#include <boost/fusion/support/category_of.hpp>
#include <boost/mpl/bool.hpp>

namespace boost { namespace fusion {

namespace detail {

  template <typename First, typename Last, typename F>
  inline void
  for_each_member_linear(First const& first,
      Last const& last,
      F const& f,
      boost::mpl::true_) {}

  template <typename First, typename Last, typename F>
  inline void
  for_each_member_linear(First const& first,
      Last const& last,
      F const& f,
      boost::mpl::false_) {

      f(
                extension::struct_member_name<
                    typename First::seq_type, First::index::value
                >::call(),
                *first
            );

      for_each_member_linear(
          next(first),
          last,
          f,
          result_of::equal_to< typename result_of::next<First>::type, Last>()
      );
  }

  template <typename Sequence, typename F>
  inline void
  for_each_member(Sequence& seq, F const& f) {

    detail::for_each_member_linear(
      fusion::begin(seq),
      fusion::end(seq),
      f,
      result_of::equal_to<
        typename result_of::begin<Sequence>::type,
        typename result_of::end<Sequence>::type>()
    );
  }

}

  template <typename Sequence, typename F>
  inline void
  for_each_member(Sequence& seq, F f) {
    detail::for_each_member(seq, f);
  }

}}

#endif 

回答by Pamela

I wrote a version without Boost or other third-party library, which has been tested using GCC 4.9(c++11), clang 5.0(c++11), VS 2008, VS 2019.

我写了一个没有 Boost 或其他第三方库的版本,已经使用 GCC 4.9(c++11)、clang 5.0(c++11)、VS 2008、VS 2019 进行了测试。

#include <iostream>
#include <string>

#define REFLECTION_WITH_FIELD_NAME 1

#define _PP_EVAL(...) __VA_ARGS__
#define _PP_EAT(...)
#define _PP_EMPTY
#define _PP_STR2(x) #x
#define _PP_STR(x) _PP_STR2(x)

#define _PP_MAP01(f, x) f(x)
#define _PP_MAP02(f, x, ...) f(x) _PP_EVAL(_PP_MAP01(f, __VA_ARGS__))
#define _PP_MAP03(f, x, ...) f(x) _PP_EVAL(_PP_MAP02(f, __VA_ARGS__))
#define _PP_MAP04(f, x, ...) f(x) _PP_EVAL(_PP_MAP03(f, __VA_ARGS__))
#define _PP_MAP05(f, x, ...) f(x) _PP_EVAL(_PP_MAP04(f, __VA_ARGS__))
#define _PP_MAP06(f, x, ...) f(x) _PP_EVAL(_PP_MAP05(f, __VA_ARGS__))
#define _PP_MAP07(f, x, ...) f(x) _PP_EVAL(_PP_MAP06(f, __VA_ARGS__))
#define _PP_MAP08(f, x, ...) f(x) _PP_EVAL(_PP_MAP07(f, __VA_ARGS__))
#define _PP_MAP09(f, x, ...) f(x) _PP_EVAL(_PP_MAP08(f, __VA_ARGS__))
#define _PP_MAP10(f, x, ...) f(x) _PP_EVAL(_PP_MAP09(f, __VA_ARGS__))
#define _PP_MAP11(f, x, ...) f(x) _PP_EVAL(_PP_MAP10(f, __VA_ARGS__))
#define _PP_MAP12(f, x, ...) f(x) _PP_EVAL(_PP_MAP11(f, __VA_ARGS__))
#define _PP_MAP13(f, x, ...) f(x) _PP_EVAL(_PP_MAP12(f, __VA_ARGS__))
#define _PP_MAP14(f, x, ...) f(x) _PP_EVAL(_PP_MAP13(f, __VA_ARGS__))
#define _PP_MAP15(f, x, ...) f(x) _PP_EVAL(_PP_MAP14(f, __VA_ARGS__))
#define _PP_MAP16(f, x, ...) f(x) _PP_EVAL(_PP_MAP15(f, __VA_ARGS__))
#define _PP_MAP17(f, x, ...) f(x) _PP_EVAL(_PP_MAP16(f, __VA_ARGS__))
#define _PP_MAP18(f, x, ...) f(x) _PP_EVAL(_PP_MAP17(f, __VA_ARGS__))
#define _PP_MAP19(f, x, ...) f(x) _PP_EVAL(_PP_MAP18(f, __VA_ARGS__))
#define _PP_MAP20(f, x, ...) f(x) _PP_EVAL(_PP_MAP19(f, __VA_ARGS__))
#define _PP_MAP21(f, x, ...) f(x) _PP_EVAL(_PP_MAP20(f, __VA_ARGS__))
#define _PP_MAP22(f, x, ...) f(x) _PP_EVAL(_PP_MAP21(f, __VA_ARGS__))
#define _PP_MAP23(f, x, ...) f(x) _PP_EVAL(_PP_MAP22(f, __VA_ARGS__))
#define _PP_MAP24(f, x, ...) f(x) _PP_EVAL(_PP_MAP23(f, __VA_ARGS__))
#define _PP_MAP25(f, x, ...) f(x) _PP_EVAL(_PP_MAP24(f, __VA_ARGS__))
#define _PP_MAP26(f, x, ...) f(x) _PP_EVAL(_PP_MAP25(f, __VA_ARGS__))
#define _PP_MAP27(f, x, ...) f(x) _PP_EVAL(_PP_MAP26(f, __VA_ARGS__))
#define _PP_MAP28(f, x, ...) f(x) _PP_EVAL(_PP_MAP27(f, __VA_ARGS__))
#define _PP_MAP29(f, x, ...) f(x) _PP_EVAL(_PP_MAP28(f, __VA_ARGS__))
#define _PP_MAP30(f, x, ...) f(x) _PP_EVAL(_PP_MAP29(f, __VA_ARGS__))
#define _PP_MAP31(f, x, ...) f(x) _PP_EVAL(_PP_MAP30(f, __VA_ARGS__))
#define _PP_MAP32(f, x, ...) f(x) _PP_EVAL(_PP_MAP31(f, __VA_ARGS__))
#define _PP_MAP33(f, x, ...) f(x) _PP_EVAL(_PP_MAP32(f, __VA_ARGS__))
#define _PP_MAP34(f, x, ...) f(x) _PP_EVAL(_PP_MAP33(f, __VA_ARGS__))
#define _PP_MAP35(f, x, ...) f(x) _PP_EVAL(_PP_MAP34(f, __VA_ARGS__))
#define _PP_MAP36(f, x, ...) f(x) _PP_EVAL(_PP_MAP35(f, __VA_ARGS__))
#define _PP_MAP37(f, x, ...) f(x) _PP_EVAL(_PP_MAP36(f, __VA_ARGS__))
#define _PP_MAP38(f, x, ...) f(x) _PP_EVAL(_PP_MAP37(f, __VA_ARGS__))
#define _PP_MAP39(f, x, ...) f(x) _PP_EVAL(_PP_MAP38(f, __VA_ARGS__))
#define _PP_MAP40(f, x, ...) f(x) _PP_EVAL(_PP_MAP39(f, __VA_ARGS__))
#define _PP_MAP41(f, x, ...) f(x) _PP_EVAL(_PP_MAP40(f, __VA_ARGS__))
#define _PP_MAP42(f, x, ...) f(x) _PP_EVAL(_PP_MAP41(f, __VA_ARGS__))
#define _PP_MAP43(f, x, ...) f(x) _PP_EVAL(_PP_MAP42(f, __VA_ARGS__))
#define _PP_MAP44(f, x, ...) f(x) _PP_EVAL(_PP_MAP43(f, __VA_ARGS__))
#define _PP_MAP45(f, x, ...) f(x) _PP_EVAL(_PP_MAP44(f, __VA_ARGS__))
#define _PP_MAP46(f, x, ...) f(x) _PP_EVAL(_PP_MAP45(f, __VA_ARGS__))
#define _PP_MAP47(f, x, ...) f(x) _PP_EVAL(_PP_MAP46(f, __VA_ARGS__))
#define _PP_MAP48(f, x, ...) f(x) _PP_EVAL(_PP_MAP47(f, __VA_ARGS__))
#define _PP_MAP49(f, x, ...) f(x) _PP_EVAL(_PP_MAP48(f, __VA_ARGS__))
#define _PP_MAP50(f, x, ...) f(x) _PP_EVAL(_PP_MAP49(f, __VA_ARGS__))
#define _PP_MAP51(f, x, ...) f(x) _PP_EVAL(_PP_MAP50(f, __VA_ARGS__))
#define _PP_MAP52(f, x, ...) f(x) _PP_EVAL(_PP_MAP51(f, __VA_ARGS__))
#define _PP_MAP53(f, x, ...) f(x) _PP_EVAL(_PP_MAP52(f, __VA_ARGS__))
#define _PP_MAP54(f, x, ...) f(x) _PP_EVAL(_PP_MAP53(f, __VA_ARGS__))
#define _PP_MAP55(f, x, ...) f(x) _PP_EVAL(_PP_MAP54(f, __VA_ARGS__))
#define _PP_MAP56(f, x, ...) f(x) _PP_EVAL(_PP_MAP55(f, __VA_ARGS__))
#define _PP_MAP57(f, x, ...) f(x) _PP_EVAL(_PP_MAP56(f, __VA_ARGS__))
#define _PP_MAP58(f, x, ...) f(x) _PP_EVAL(_PP_MAP57(f, __VA_ARGS__))
#define _PP_MAP59(f, x, ...) f(x) _PP_EVAL(_PP_MAP58(f, __VA_ARGS__))
#define _PP_MAP60(f, x, ...) f(x) _PP_EVAL(_PP_MAP59(f, __VA_ARGS__))
#define _PP_MAP61(f, x, ...) f(x) _PP_EVAL(_PP_MAP60(f, __VA_ARGS__))
#define _PP_MAP62(f, x, ...) f(x) _PP_EVAL(_PP_MAP61(f, __VA_ARGS__))
#define _PP_MAP63(f, x, ...) f(x) _PP_EVAL(_PP_MAP62(f, __VA_ARGS__))
#define _PP_MAP64(f, x, ...) f(x) _PP_EVAL(_PP_MAP63(f, __VA_ARGS__))

#define _PP_GET_NTH_ARG( \
  _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, \
  _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, \
  _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, \
  _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, \
  _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, \
  _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, \
  _61, _62, _63, _64, N, ...) N

#define _PP_MAP(f, ...) _PP_EVAL(_PP_EVAL(_PP_GET_NTH_ARG(__VA_ARGS__, \
  _PP_MAP64, _PP_MAP63, _PP_MAP62, _PP_MAP61, \
  _PP_MAP60, _PP_MAP59, _PP_MAP58, _PP_MAP57, _PP_MAP56, \
  _PP_MAP55, _PP_MAP54, _PP_MAP53, _PP_MAP52, _PP_MAP51, \
  _PP_MAP50, _PP_MAP49, _PP_MAP48, _PP_MAP47, _PP_MAP46, \
  _PP_MAP45, _PP_MAP44, _PP_MAP43, _PP_MAP42, _PP_MAP41, \
  _PP_MAP40, _PP_MAP39, _PP_MAP38, _PP_MAP37, _PP_MAP36, \
  _PP_MAP35, _PP_MAP34, _PP_MAP33, _PP_MAP32, _PP_MAP31, \
  _PP_MAP30, _PP_MAP29, _PP_MAP28, _PP_MAP27, _PP_MAP26, \
  _PP_MAP25, _PP_MAP24, _PP_MAP23, _PP_MAP22, _PP_MAP21, \
  _PP_MAP20, _PP_MAP19, _PP_MAP18, _PP_MAP17, _PP_MAP16, \
  _PP_MAP15, _PP_MAP14, _PP_MAP13, _PP_MAP12, _PP_MAP11, \
  _PP_MAP10, _PP_MAP09, _PP_MAP08, _PP_MAP07, _PP_MAP06, \
  _PP_MAP05, _PP_MAP04, _PP_MAP03, _PP_MAP02, _PP_MAP01 \
  ))(f, __VA_ARGS__))

#if REFLECTION_WITH_FIELD_NAME
#define _PP_REFLECTION_FIELD_NAME(x) _PP_STR(_PP_EVAL(x))
#else
#define _PP_REFLECTION_FIELD_NAME(x) ""
#endif

#define _PP_REFLECTION_ALL(x) _PP_EVAL x
#define _PP_REFLECTION_SECOND(x) _PP_EAT x
#define _PP_REFLECTION_FIELD(x) _PP_REFLECTION_ALL(x);
#define _PP_REFLECTION_METHOD2(x) v(this, _PP_REFLECTION_FIELD_NAME(x), x);
#define _PP_REFLECTION_METHOD(x) _PP_REFLECTION_METHOD2(_PP_REFLECTION_SECOND(x))

#define _PP_REFLECTION_VISTOR_METHOD(type, ...) \
  template <class Vistor> \
  void _reflect(Vistor& v) type { \
    _PP_MAP(_PP_REFLECTION_METHOD, __VA_ARGS__) \
  }

#define REFLECT(...) \
  _PP_MAP(_PP_REFLECTION_FIELD, __VA_ARGS__) \
  _PP_REFLECTION_VISTOR_METHOD(_PP_EMPTY, __VA_ARGS__) \
  _PP_REFLECTION_VISTOR_METHOD(const, __VA_ARGS__)


// Usage of REFLECT()

#define OBJECT_NAME_METHOD(obj) \
  static const char* object_name() { \
    return #obj; \
  }

struct Demo
{
  OBJECT_NAME_METHOD(Demo)

  REFLECT(
    (int) a,
    (int) b,
    (std::string) c
  )

  int d; // DO NOT REFLECT
};

struct Amplifier {
  template <class Obj>
  void apply(Obj* obj) {
    obj->_reflect(*this);
  }

  template <class Obj, class Field>
  void operator() (Obj* /*obj*/, const char* /*name*/, Field& field) {
    field *= 100;
  }

  template <class Obj>
  void operator() (Obj* /*obj*/, const char* /*name*/, std::string& field) {
    field += "00";
  }
};

struct Printer {
  template <class Obj>
  void print(const Obj& obj) {
    obj._reflect(*this);
  }

  template <class Obj, class Field>
  void operator() (Obj* obj, const char* name, const Field& field) {
    std::cout << obj->object_name() << "."
      << name << ": " << field << std::endl;
  }
};

int main() {
  Demo a = {100, 200, "300", 400};

  Amplifier amplifier;
  amplifier.apply(&a);

  Printer printer;
  printer.print(a);
}

/*
Output:
Demo.a: 10000
Demo.b: 20000
Demo.c: 30000
*/

BTW, the following code is used for generating all _PP_MAP_? macros (written in JS, so you can run it in web browser).

顺便说一句,以下代码用于生成所有_PP_MAP_?宏(用 JS 编写,因此您可以在 Web 浏览器中运行它)。

(function() {
  const maxNumOfEle = 64;
  const mapNamePrefix = '_PP_MAP';
  let codeText = '';

  function formatNumWidth(num) {
    return ("0" + num).slice(-2);
  }

  function AddNewLine() {
    if (codeText.slice(-1) != ' ') {
      codeText += ' ';
    }

    codeText += '\\n';
    codeText += ' '.repeat(2);
  }

  codeText += `#define ${mapNamePrefix}${formatNumWidth(1)}(f, x) f(x)\n`;
  for (let i = 2; i <= maxNumOfEle; ++i) {
    let funId = formatNumWidth(i);
    codeText += `#define ${mapNamePrefix}${funId}(f, x, ...) f(x)`;

    let nextFunId = formatNumWidth(i - 1);
    codeText += ' _PP_EVAL(';
    codeText += `${mapNamePrefix}${nextFunId}(f, __VA_ARGS__)`;
    codeText += ')';

    codeText += '\n';
  }

  codeText += '\n#define _PP_GET_NTH_ARG(';
  AddNewLine();
  for (let i = 1; i <= maxNumOfEle; ++i) {
    codeText += `_${i}, `;
    if ((i % 10) == 0) {
      AddNewLine();
    }
  }
  codeText += 'N, ...) N\n';

  codeText += `\n#define ${mapNamePrefix}(f, ...) `;
  codeText += '_PP_EVAL(_PP_EVAL(_PP_GET_NTH_ARG(__VA_ARGS__,';
  AddNewLine();
  for (let i = maxNumOfEle; i >= 1; --i) {
    let funId = formatNumWidth(i);
    codeText += `${mapNamePrefix}${funId}`;
    if (i != 1) {
      codeText += ', ';
    }

    if ((i % 5) == 1) {
      AddNewLine();
    }
  }
  codeText += '))(f, __VA_ARGS__))\n';

  console.log(codeText);
})();

回答by Larytet

If all fields in the structure are the same, you can do

如果结构中的所有字段都相同,则可以执行

template <typename S> uint64_t* get_begin(S *s)
{
    return (uint64_t*)s;
}

template <typename S> uint64_t* get_end(S *s)
{
    return (uint64_t*)((uint8_t*)s+sizeof(*s));
}

struct statistics_s {
        uint64_t f1;
        uint64_t f2;
} statistics;

for (uint64_t* p = get_begin(&statistics);p < get_end(&statistics);p++)
    printf("%lu ", *p);