【问题标题】:instantiating template functions and classes with boost preprocess使用 boost 预处理实例化模板函数和类
【发布时间】:2017-06-18 07:34:11
【问题描述】:

使用看似标准的 wxyz 演示,假设我有以下宏试图转换为“可迭代”预处理器宏

#define INSTANTIATE_FUNC(rtype, func_name, ...)  \
    template rtype func_name< w > (__VA_ARGS__); \
    template rtype func_name< x > (__VA_ARGS__); \
    template rtype func_name< y > (__VA_ARGS__); \
    template rtype func_name< z > (__VA_ARGS__);

为了完整起见,假设我们正在尝试实例化以下内容

struct w { static constexpr int data = 0; };
struct x { static constexpr int data = 1; };
struct y { static constexpr int data = 2; };
struct z { static constexpr int data = 3; };

template <class Data>
void printData(const std::string &prefix) {
    std::cout << prefix << Data::data << std::endl;
}

INSTANTIATE_FUNC(void, printData, const std::string &prefix)

为了方便起见,我创建了一个minimal gist with a build system,这样如果您有兴趣尝试,就不必重新创建所有内容:)

我不知道如何处理这个问题。唯一有功能(但没用)的刺

#include <boost/preprocessor/list/for_each.hpp>

#define LIST (w, (x, (y, (z, BOOST_PP_NIL))))
#define MACRO(r, data, elem) template void data < elem > (const std::string &prefix);

#define INSTANTIATE_FUNC(rtype, func_name, ...) \
    BOOST_PP_LIST_FOR_EACH(MACRO, func_name, LIST)

这是可行的,但显然还不够。

  1. 为什么这不适用于序列?

    #include <boost/preprocessor/seq/for_each.hpp>
    // this does work, my code included the wrong header
    // on what I was testing with (seq/for_each_i.hpp)
    
    #define SEQ (x)(y)(z)(w)
    #define INSTANTIATE_FUNC(rtype, func_name, ...) \
        BOOST_PP_SEQ_FOR_EACH(MACRO, func_name, SEQ)
    
  2. 我应该如何构建template rtype func_name &lt; {w,x,y,z} &gt; {args,in,__VA_ARGS__}?我尝试了很多不同的东西,但问题似乎无法解决,例如只提取w,然后循环遍历__VA_ARGS__,然后继续。我一直在努力让BOOST_PP_LIST_FOR_EACH_R 工作。这至少是正确的吗?

  3. 作为健全性检查,您不能在宏中定义宏,对吧?本着精神的东西

    #define INSTANTIATE_FUNC(rtype, func_name, ...) \
        #define MACRO_##func_name(r, data, elem) data < elem > (__VA_ARGS__); \
        BOOST_PP_LIST_FOR_EACH(MACRO_##func_name, func_name, LIST)
    

我最终将朝着启用LIST/SEQ 的可选扩展的目标努力(SEQ 似乎更容易实现这一点)如果这意味着什么。感谢您提供任何建议/资源。

【问题讨论】:

    标签: c++ c++11 boost macros


    【解决方案1】:

    您的问题似乎是您需要在BOOST_PP_(LIST|SEQ)_FOR_EACH 中向您的MACRO 传递几条数据,并且您只能使用一个“插槽”。您似乎缺少的事实是,您可以将这些片段分组到一个元组中,然后使用BOOST_PP_TUPLE_ELEM 访问您的MACRO 中的不同元素。像这样的东西可以工作:

    //These are not required, just to help with readability
    #define MACRO_GET_RETURN_TYPE(TUPLE)  BOOST_PP_TUPLE_ELEM(3,0,TUPLE)
    #define MACRO_GET_FUNC_NAME(TUPLE)  BOOST_PP_TUPLE_ELEM(3,1,TUPLE)
    #define MACRO_GET_ARGS_SEQ(TUPLE)  BOOST_PP_TUPLE_ELEM(3,2,TUPLE)
    
    
    #define MACRO(_, DATA, ELEM) template MACRO_GET_RETURN_TYPE(DATA) MACRO_GET_FUNC_NAME(DATA) < ELEM > (BOOST_PP_SEQ_ENUM(MACRO_GET_ARGS_SEQ(DATA)));
    
    // with boost seq
    #define SEQ (x)(y)(z)(w)
    
    #define INSTANTIATE_FUNC(rtype, func_name, ...) \
        BOOST_PP_SEQ_FOR_EACH(MACRO, (rtype,func_name,BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__)), SEQ)
    

    Live on Wandbox

    PS:不,您不能在宏中定义宏,并且您在此处发布的代码确实适用于序列,您的要点中的代码不是由于使用了错误的标题。

    【讨论】:

    • 哇!是的,我完全不知道我可以“元组化”我的宏。这是纯粹的魔法,彻底改变了游戏规则。有了这个能力,我可以比我最初想象的更进一步。啊哈哈哈哈。我知道这必须是可能的。感谢您向我展示如何:)是的,后面的i 对序列faceslap 产生了巨大的影响。作为额外的奖励,wandboxgist 更好...
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-30
    • 1970-01-01
    • 2016-01-04
    • 1970-01-01
    相关资源
    最近更新 更多