所有结构成员的预处理器批处理

Preprocessor batch for all structure members

本文关键字:预处理 处理器 批处理 成员 结构      更新时间:2023-10-16

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

我有这样一个结构(从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++14开始,是的,我们确实有(几乎所有)聚合类型的编译时反射,请参阅Antony Polukhin的magic get库(以及此cppcon演示文稿,了解其工作原理)。我认为您也可以在c++11中使用一些ABI支持。

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

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

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


现在,鉴于上述情况,更明智的做法是避免像现在这样依赖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应该是一个数组,现在将获得两个偏移

没有"自动"手段,没有

不幸的是,你的结构是自动生成的。如果它们完全在你的控制之下,我建议使用这里描述的REFLECTABLE宏。

请阅读答案,也许你可以重组你的代码和/或工作流程,使其发挥作用?