【问题标题】:Preprocessor batch for all structure members所有结构成员的预处理器批处理
【发布时间】:2018-04-27 11:44:09
【问题描述】:

是否可以编写一个自动迭代结构的所有成员的预处理器宏?

我有这样一个结构(从 Simulink 模型自动生成):

typedef struct {
  real_T driveStatusword;
  real_T posSensor[2];
  real_T softAbortDemand;
} ExtU_motionCtrlRTOS_T;

还有一个类似的:

struct CoreInputOffsets
{
    uint32_t driveStatusword;
    uint32_t posSensor;
    uint32_t softAbortDemand;
};

而我想做这样的操作:

void getCoreInputOffsets(CoreInputOffsets* pCoreInputOffsets)
{
    pCoreInputOffsets->driveStatusword = offsetof(ExtU_motionCtrlRTOS_T, driveStatusword);
    pCoreInputOffsets->posSensor = offsetof(ExtU_motionCtrlRTOS_T, posSensor);
    pCoreInputOffsets->softAbortDemand = offsetof(ExtU_motionCtrlRTOS_T, softAbortDemand);
}

但不必在每次结构更改时编辑此函数,通过迭代CoreInputOffsets 的所有成员。

【问题讨论】:

标签: c++ c-preprocessor


【解决方案1】:

没有“自动”的意思,没有。

不幸的是,您的结构是自动生成的。如果它们在您的完全控制之下,我会推荐 REFLECTABLE 宏,就像它在 here 中所描述的那样。

请阅读该答案,也许您可​​以重组您的代码和/或工作流程以使其正常工作?

【讨论】:

    【解决方案2】:

    从 c++14 开始,是的,我们确实有(几乎所有)聚合类型的编译时反射,请参阅 Antony Polukhinmagic get library(和 this cppcon 演示文稿以了解它是如何实现的作品)。我认为你也可以在 C++11 中使用一些 ABI 支持。

    例如,要分配给ExtU_motionCtrlRTOS_T x;,您只需编写

    boost::pfr::flat_structure_tie(x) = boost::pfr::flat_structure_tie(some_unrelated_pod);
    

    我假设成员是按顺序分配的。请注意,我使用 flat tie 版本,按元素分配嵌套数组。


    现在,鉴于上述情况,最好避免像您现在所做的那样依赖 offsetof() 并利用所有编译时间信息进行相关操作(这也可能会为您提供更快的代码)。

    无论如何,如果您仍想获得偏移量,您的代码的逐字转录可能如下所示:

    #include <boost/pfr/flat/core.hpp>
    
    struct CoreInputOffsets
    {
        uint32_t driveStatusword;
        uint32_t posSensor[2];
        uint32_t softAbortDemand;
    };
    
    template <typename T,std::size_t... Is>
    void assignOffsets( CoreInputOffsets& offsets, std::index_sequence<Is...> )
    {
      T t;
      (( boost::pfr::flat_get<Is>(offsets) = reinterpret_cast<char*>(&boost::pfr::flat_get<Is>(t)) - reinterpret_cast<char*>(&boost::pfr::flat_get<0>(t)) ), ...);
    }
    
    template <typename T>
    void assignOffsets( CoreInputOffsets& offsets )
    {
      assignOffsets<T>( offsets, std::make_index_sequence< boost::pfr::flat_tuple_size<T>::value >{} );
    }
    
    void getCoreInputOffsets(CoreInputOffsets* pCoreInputOffsets)
    {
      assignOffsets<ExtU_motionCtrlRTOS_T>( *pCoreInputOffsets );
    }
    

    注意事项

    • 这是 c++17(不过您可以使其符合 c++14)
    • 获取实际偏移量的代码需要一个虚拟的 ExtU_motionCtrlRTOS_T;我想这没什么大不了的,因为你只会分配一次,我想
    • 通过指针减法获取实际偏移量的代码在标准方面给出了未定义的行为,您需要验证它对于您的平台是否合法
    • CoreInputOffsets::posSensor 应该是一个数组,现在将获得 两个 偏移量

    【讨论】:

    • 最好的部分是它不需要任何讨厌的预处理器接口。
    • 它现在被称为 PFR(Precise and Fat Reflection),看起来正朝着 Boost 方向发展。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-25
    • 1970-01-01
    • 2020-02-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多