【问题标题】:Iterating over a struct in C++遍历 C++ 中的结构
【发布时间】:2013-07-15 17:23:41
【问题描述】:

我有一个结构

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

我想遍历结构的每个成员并打印其值。比如:

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

如何在 C++ 中做到这一点??

【问题讨论】:

  • 从更简单的开始:您将如何打印Aa 字段?
  • 您的样本看起来像是过时的c。在我的回答中,作为旁注,我已经解决了这些问题。
  • 除非您的数据结构的字段在运行时之前未确定,否则我看不到它的用途。在这种情况下, typedef struct 不是处理您想要完成的任何事情的正确方法。
  • 在 C++14 中成为可能,请参阅本讲座:CppCon 2016: C++14 Reflections without Macros, Markup or External Tooling.. youtube.com/watch?v=abdeAew3gmQ
  • 查看:相关question、我的示例solution 和惊人的Boost.PFR

标签: c++ struct


【解决方案1】:

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

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");
}

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

BOOST_FUSION_ADAPT_STRUCT(A,a,b,c);

输出:

1
42
The Answer To LtUaE

【讨论】:

  • 如果 Boost 可以做到,那么我们在这里也可以,没有 Boost...
【解决方案2】:

您不能迭代对象的数据成员。您可以使用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';
    }
};

在main里面:

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

    std::cout << a;
}

输出:

5
10
苹果酱

Here is a demo.

【讨论】:

  • 这使我的调试更容易,并帮助我立即发现了一些错误。
  • 请注意,将输出流函数添加到结构需要以某种方式声明结构,因此如果有人在尝试实现这一点时遇到错误,结构名称的位置(在本例中, A) 是一个不错的首选。 struct A { ... };typedef struct A { ... } A; 都可以,但 typedef struct { ... } A; 会给你带来麻烦。
  • 这没有回答如何打印成员 names,这是问题的一部分。
  • @Wand return os &lt;&lt; "a: " &lt;&lt; a.a &lt;&lt; '\n' &lt;&lt; ...
  • @TᴏᴍᴇʀWᴏʟʙᴇʀɢ 是的,可以。我希望会有一些更“反思”的东西,不需要硬编码任何东西,但在过去的几个月里,我一直在使用像 Boost.Hana 这样的“反思”元编程库,它们确实提供了对成员名称的迭代,而且它事实证明,像宏 BOOST_HANA_DEFINE_STRUCT(参见Structure Concept in Hana)之类的东西最终只是使用预处理器从其参数中生成这些硬编码函数......
【解决方案3】:

有几种方法可以做到这一点,但您需要使用一些宏来定义或调整结构。

您可以使用this answer 中给出的REFLECTABLE 宏来定义这样的结构:

struct A
{
    REFLECTABLE
    (
        (int) a,
        (int) b,
        (const char *) c
    )
};

然后您可以遍历字段并像这样打印每个值:

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);

另一种方法是将结构调整为融合序列(参见the documentation)。这是一个例子:

struct A
{
    int a;
    int b;
    const char * c;
};

BOOST_FUSION_ADAPT_STRUCT
(
    A,
    (int, a)
    (int, b)
    (const char *, c)
)

然后您也可以使用以下方法打印字段:

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)));
}

【讨论】:

    【解决方案4】:

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

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

    【讨论】:

      【解决方案5】:

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

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

      反射”(因为这种类型的功能通常被称为不是 C++ 的一部分)。


      c++11 中,您可以使用 std::tuple&lt;int,int,char*&gt; 而不是 struct A,它将存储相同类型的元素并且更容易迭代(使用一些 模板魔法)。

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

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


      【讨论】:

        【解决方案6】:

        正如@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 
        

        【讨论】:

          【解决方案7】:

          如果结构中的所有字段都相同,则可以这样做

          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);
          

          【讨论】:

          • 这假设结构成员之间没有填充。
          【解决方案8】:

          我写了一个没有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
          */
          

          顺便说一句,以下代码用于生成所有_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);
          })();
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2019-09-28
            • 1970-01-01
            • 2011-03-06
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2015-02-02
            相关资源
            最近更新 更多