根据参数数量生成多个宏调用 [英] Generate multiple macro calls according to the number of arguments

查看:98
本文介绍了根据参数数量生成多个宏调用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图以重复的方式多次调用此函数.

I'm trying to call this function several times in a repeditive fashion.

template<class T>
void METADATA_METHODS_IMPL(std::string& metadata, const T &value, const std::string &key)
{
    metadata += boost::format("%1%:%2%") % key % value();
}

我写了以下宏:

#define METADATA_METHODS_IMPL_1(md, v1)\
   METADATA_METHODS_IMPL(md, v1, #v1);

#define METADATA_METHODS_IMPL_2(md, v1, v2)\
   METADATA_METHODS_IMPL_1(md, v1)\
   METADATA_METHODS_IMPL_1(md, v2)

#define METADATA_METHODS_IMPL_3(md, v1, v2, v3)\
   METADATA_METHODS_IMPL_2(md, v1, v2)\
   METADATA_METHODS_IMPL_1(md, v3)

以此类推...

我需要调用METADATA_METHODS_IMPL_N,其中N__VA_ARGS__中的多个参数

I need to call METADATA_METHODS_IMPL_N where N is a number of arguments in __VA_ARGS__

#define METADATA_METHODS(...)\
std::string METADATA_METHODS_IMPL_FUNC()\
{\
    std::string metadata;\
    BOOST_PP_OVERLOAD(METADATA_METHODS_IMPL_,__VA_ARGS__)(metadata, __VA_ARGS__)\
    return metadata;\
}

上面的代码(带有BOOST_PP_OVERLOAD)给了我不合适的结果:

The code above (with BOOST_PP_OVERLOAD) gives me unsuitable result:

class X
{
    std::string F1();
    std::string F2();
    std::string F3();

    METADATA_METHODS(F1, F2, F3);
};

这导致

std::string METADATA_METHODS_IMPL_FUNC() 
{
    std::string metadata; 
    METADATA_METHODS_IMPL(metadata, F1, F2, F3, "F1", "F2", "F3"); 
    METADATA_METHODS_IMPL(metadata, , ""); 
    METADATA_METHODS_IMPL(metadata, , ""); 
    return metadata; 
};

我想要这样的东西:

std::string METADATA_METHODS_IMPL_FUNC() 
{
    std::string metadata; 
    METADATA_METHODS_IMPL(metadata, F1, "F1"); 
    METADATA_METHODS_IMPL(metadata, F2, "F2"); 
    METADATA_METHODS_IMPL(metadata, F3, "F3"); 
    return metadata; 
};

  • 有人知道如何达到预期的结果吗?
  • 我可以使用Boost.preprocessor库为使用METADATA_METHODS_IMPL_1的某些K in [1 .. 10]自动生成METADATA_METHODS_IMPL_K
    • Does anyone know how to achieve the desired result?
    • Can I use Boost.preprocessor library to automagically generate METADATA_METHODS_IMPL_K for some K in [1 .. 10] using METADATA_METHODS_IMPL_1
    • 推荐答案

      使用这些宏,我们可以使预处理器保持重新扫描并允许递归宏.

      Using these macros we can cause the preprocessor to keep rescanning and allow for recursive macros.

      #define EVAL(...)  EVAL3(EVAL3(EVAL3(__VA_ARGS__)))
      #define EVAL3(...) EVAL2(EVAL2(EVAL2(__VA_ARGS__)))
      #define EVAL2(...) EVAL1(EVAL1(EVAL1(__VA_ARGS__)))
      #define EVAL1(...) EVAL0(EVAL0(EVAL0(__VA_ARGS__)))
      #define EVAL0(...) __VA_ARGS__
      

      我们可以定义一些辅助函数来构建概念.

      We can define some helper functions to build up concepts.

      #define CAT(a, ...) PRIMITIVE_CAT(a,__VA_ARGS__)
      #define PRIMITIVE_CAT(a, ...) a ## __VA_ARGS__
      
      #define EMPTY()
      #define EAT(...)
      #define IDENT(...) __VA_ARGS__
      #define DEFER(id) id EMPTY()
      #define OBSTRUCT(...) __VA_ARGS__ DEFER(EMPTY)()   
      
      #define I_TRUE(t,f) t
      #define I_FALSE(t,f) f
      #define I_IS_DONE(a,b,...) b
      #define TRUE_DONE() ~, I_TRUE
      #define IS_DONE(b) OBSTRUCT(I_IS_DONE)(CAT(TRUE_,b)(),I_FALSE) 
      

      并构建此宏映射函数,该函数将第一个参数传递给每个宏.

      And build this Macro Mapping function that carries the first parameter to each.

      #define MM() MM_CALL
      #define MM_NEXT(Macro,md,a,...) \
        IS_DONE(a)(                    \
           EAT                          \
        ,                                \
           OBSTRUCT(MM)()                 \
        )                                  \
        (Macro,md,a,__VA_ARGS__)
      #define MM_CALL(Macro,md,a,...)   \
        Macro(md,a)                      \
        MM_NEXT(Macro,md,__VA_ARGS__)
      #define MacroMap(Macro,md,...) EVAL(MM_CALL(Macro,md,__VA_ARGS__,DONE))
      

      定义实现相关功能后

      #define METADATA_METHODS_IMPL_MACRO(md,a) \
        METADATA_METHODS_IMPL(md, a, #a);
      
      #define METADATA_METHODS(md,...) \
        MacroMap(METADATA_METHODS_IMPL_MACRO,md,__VA_ARGS__) \
        return md
      

      此:

      METADATA_METHODS(metadata, F1, F2, F3);
      

      结果(添加一些格式后):

      Results in this (after adding some formatting):

      METADATA_METHODS_IMPL(metadata, F1, "F1");
      METADATA_METHODS_IMPL(metadata, F2, "F2");
      METADATA_METHODS_IMPL(metadata, F3, "F3");
      return metadata;
      

      这篇关于根据参数数量生成多个宏调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆