是否可以编写一个预处理器宏来自动迭代结构的所有成员?
我有这样一个结构(从 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 library (和 this cppcon 演示以了解其工作原理)。我认为您还可以通过一些 ABI 支持使其在 c++11 中工作。
例如,要分配给 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 应该是一个数组,现在将得到两个偏移量
关于c++ - 所有结构成员的预处理器批处理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47287263/