C++ 助推融合类型偏移

C++ 助推融合类型偏移,c++,boost,boost-fusion,offsetof,C++,Boost,Boost Fusion,Offsetof,我目前正在尝试计算boost fusion自适应结构中数据成员的偏移量,但我不确定是否有一种优雅的方法可以做到这一点。我想做如下事情: #include <iostream> #include <boost/fusion/adapted/struct/adapt_struct.hpp> #include <boost/fusion/include/adapt_struct.hpp> #include <boost/fusion/sequence/int

我目前正在尝试计算boost fusion自适应结构中数据成员的偏移量,但我不确定是否有一种优雅的方法可以做到这一点。我想做如下事情:

#include <iostream> 
#include <boost/fusion/adapted/struct/adapt_struct.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/fusion/sequence/intrinsic/at.hpp>
#include <boost/fusion/include/at.hpp>
#include <cstddef.h>

   struct test {
      int a;  
      char c;  
      double b;  
    };

BOOST_FUSION_ADAPT_STRUCT(
  test, 
  (int, a)
  (char, c)
  (double, b)
)

int main() {
test s{1, 2, 3.0}; 
// The following code doesn't work... I'm just trying to get my point across
std::cout << "offset is :" << offsetof(test, at<1>(s)) << std::endl;
}
#包括
#包括
#包括
#包括
#包括
#包括
结构测试{
INTA;
字符c;
双b;
};
增强融合适应结构(
测试,
(国际,a)
(char,c)
(双份,b)
)
int main(){
测试s{1,2,3.0};
//下面的代码不起作用…我只是想让大家明白我的观点

std::cout我不是专家,但我认为由于
偏移量的性质,如果不需要使用宏,就无法实现您想要的。下面的示例只是使用宏为结构的每个成员创建一个特征,每当您访问它时,它都会返回预计算的偏移量

#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
名称空间不融合
{
模板
结构偏移量;
}
//实际创建每个相应的“偏移量”特征
//您可以更改“BOOST\u STATIC\u CONSTANT(std::size\u t,…)”
//使用“static constexpr std::size\u t…”或您喜欢的任何东西
#定义创建偏移量特征(R、结构名称、索引、成员)\
{BOOST_STATIC_常量(std::size_t,value=offsetof(struct_NAME,MEMBER));}的模板结构偏移量;
//迭代结构成员以创建相应的“偏移量”特征
#定义非融合保存偏移量(结构名称、成员)\
名称空间未融合{\
每个I的推进顺序(创建偏移特征、结构名称、成员)\
}
//只需“调用”BOOST\u FUSION\u ADAPT\u STRUCT和“NOT\u FUSION\u SAVE\u offset”
#定义自适应结构和保存偏移量(类型,…)\
BOOST\u FUSION\u ADAPT\u STRUCT(类型,\uuu VA\u ARGS\uuuu)\
非融合保存偏移量(类型、升压变量到顺序
结构测试1{
INTA;
字符c;
双b;
};
结构测试2{
字符c;
短s;
int i;
};
调整结构和保存偏移量(test1、a、c、b);
调整结构和保存偏移量(test2、c、s、i);
模板
无效打印偏移量(常量标准::字符串和名称,常量结构和)
{
//这可以更改为使用“std::integer_sequence”而不是mpl

std::cout可能不是一个好方法,但既然你喜欢听想法…:P.
fusion::for_each
使用c++14 lambda,如果你不能使用它们,你就需要使用一个模板函子(类似)。@cv_和_他哇。令人印象深刻。这非常漂亮(对我来说,PP宏是一个障碍;很高兴看到你正好越过它们)太酷了!谢谢分享代码!你错过了boost fusiontag@sehe完成了。我想我已经把它简化了一点。
#include <iostream> 
#include <string>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/fusion/include/at.hpp>
#include <boost/fusion/include/for_each.hpp>
#include <boost/fusion/include/mpl.hpp>

#include <boost/mpl/range_c.hpp>

#include <cstddef>

namespace not_fusion
{
    template <typename StructName, int N>
    struct offset_of;
}

//Actually creates each respective 'offset_of' trait 
//you could change 'BOOST_STATIC_CONSTANT(std::size_t,...)'
//with a 'static constexpr std::size_t ...' or whatever you like
#define CREATE_OFFSET_TRAIT(R,STRUCT_NAME,INDEX,MEMBER) \
template <> struct offset_of<STRUCT_NAME, INDEX>{ BOOST_STATIC_CONSTANT(std::size_t, value = offsetof(STRUCT_NAME,MEMBER)); };

//Iterates the struct members in order to create the corresponding 'offset_of' traits
#define NOT_FUSION_SAVE_OFFSETS(STRUCT_NAME,MEMBERS) \
namespace not_fusion { \
BOOST_PP_SEQ_FOR_EACH_I(CREATE_OFFSET_TRAIT,STRUCT_NAME,MEMBERS) \
}

//Simply "invokes" 'BOOST_FUSION_ADAPT_STRUCT' and 'NOT_FUSION_SAVE_OFFSETS'
#define ADAPT_STRUCT_AND_SAVE_OFFSETS(TYPE,...) \
BOOST_FUSION_ADAPT_STRUCT(TYPE,__VA_ARGS__) \
NOT_FUSION_SAVE_OFFSETS(TYPE,BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__))

struct test1 {
    int a;  
    char c;  
    double b;  
};

struct test2 {
    char c;
    short s;
    int i;
};

ADAPT_STRUCT_AND_SAVE_OFFSETS(test1,a,c,b);
ADAPT_STRUCT_AND_SAVE_OFFSETS(test2,c,s,i);


template <typename Struct>
void print_offsets(const std::string& name,const Struct&)
{
    //This could be changed to use 'std::integer_sequence' instead of mpl
    std::cout << "Offsets for " << name << ":" << std::endl;
    typedef boost::mpl::range_c<unsigned, 0, boost::fusion::result_of::size<Struct>::value > Indices; 
    boost::fusion::for_each(Indices(),
        [](auto index)
        { 
            std::cout << boost::fusion::extension::struct_member_name<Struct,index>::call() << " -> " << not_fusion::offset_of<Struct,index>::value << std::endl;
        }
    );
}

int main() {
    test1 t1{1, 2, 3.0}; 
    test2 t2{1,2,3};

    print_offsets("test1",t1);
    print_offsets("test2",t2);
}