C++ 结构的编译时大小减去填充

C++ 结构的编译时大小减去填充,c++,c++17,boost-mpl,compile-time-constant,boost-fusion,C++,C++17,Boost Mpl,Compile Time Constant,Boost Fusion,我尝试使用boostmpl和Fusion来计算结构的大小,不包括任何填充。这是我目前最好的尝试: 模板 constexpr std::size_t sizeof_成员(void) { 使用名称空间std; 名称空间mpl=boost::mpl; 名称空间融合=boost::fusion; //这是可行的,但只适用于正好包含4个成员的结构。。。 typedef typename mpl::apply::type成员类型; typedef typename mpl::transform::type

我尝试使用boostmpl和Fusion来计算结构的大小,不包括任何填充。这是我目前最好的尝试:

模板
constexpr std::size_t sizeof_成员(void)
{
使用名称空间std;
名称空间mpl=boost::mpl;
名称空间融合=boost::fusion;
//这是可行的,但只适用于正好包含4个成员的结构。。。
typedef typename mpl::apply::type成员类型;
typedef typename mpl::transform::type成员大小;
typedef typename mpl::accumulate::type sum;
返回和();
}
BOOST\u FUSION\u DEFINE\u STRUCT(
(),Foo_t,
(标准:uint8_t,a)
(标准:uint16_t,b)
(标准:uint32_t,c)
(标准:uint64_t,d)
);
静态_断言(sizeof_成员()==15);
int main()
{

std::cout既然您标记了这个C++17,答案是:不要使用Boost.MPL。即使考虑到C++11,您想要的元编程库是-它在各个方面都有很大的改进

更新、更易于使用、编译时效率更高的Boost.Fusion版本是:

您希望使用Boost.Hana的原因是
sizeof_成员
(适用于任意数量的成员)可以写成:

模板
constexpr auto sizeof_members()->size_t
{
返回hana::fold(hana::accessors(),size\u t{},
[](尺寸,自动记忆){
返回s+sizeof(hana::second(mem)(std::declval());
});
}
静态_断言(sizeof_成员()==15);
这与您实际想要做的完全一样:您希望从0开始折叠所有成员,使用累加函数添加下一个成员的大小(
accessors())
提供一系列对,其中
第一个
是访问器的名称,
第二个
是获取对象并返回该成员的函数)


.

既然您为这个C++17添加了标签,答案是:不要使用Boost.MPL。即使考虑到C++11,您想要的元编程库是-它在各个方面都有很大的改进

更新、更易于使用、编译时效率更高的Boost.Fusion版本是:

您希望使用Boost.Hana的原因是
sizeof_成员
(适用于任意数量的成员)可以写成:

模板
constexpr auto sizeof_members()->size_t
{
返回hana::fold(hana::accessors(),size\u t{},
[](尺寸,自动记忆){
返回s+sizeof(hana::second(mem)(std::declval());
});
}
静态_断言(sizeof_成员()==15);
这与您实际想要做的完全一样:您希望从0开始折叠所有成员,使用累加函数添加下一个成员的大小(
accessors())
提供一系列对,其中
第一个
是访问器的名称,
第二个
是获取对象并返回该成员的函数)


.

如何将其扩展到任意结构?
什么是“任意结构”你是说,对于结构没有使用<代码> BooStfExcel融合/代码>?你不能——C++没有反射。实际上,你可以在C++ 14和C++ 17中对AggregateTypes做这个。。然后你可以委托给结构分解,你就有了类型。@KamilCuk任何与Boost Fusion相适应但字段较多或较少的结构。我当前的实现仅适用于给定的具有四个字段的特定示例。
如何将其扩展到任意结构?
什么是“任意结构”你是说,对于结构没有使用<代码> BooStfExcel融合/代码>?你不能——C++没有反射。实际上,你可以在C++ 14和C++ 17中对AggregateTypes做这个。。然后你可以委托给一个结构分解,你就有了类型。@KamilCuk任何与Boost Fusion相适应的结构,但有更多或更少的字段。我当前的实现只适用于给定的具有四个字段的特定示例。这正是我想要的,比我要走的路要直接得多。当我的struct成员也是一个结构体,我如何将sizeof_成员称为recursivley?这正是我想要的,而且比我要走的路径要直接得多。当我的结构体成员也是一个结构体时,该怎么做,我如何将sizeof_成员称为recursivley?
template<class T>
constexpr std::size_t sizeof_members(void)
{
    using namespace std;
    namespace mpl = boost::mpl;
    namespace fusion = boost::fusion;

    //This works, but only for structs containing exactly 4 members...
    typedef typename mpl::apply<mpl::unpack_args<mpl::vector<mpl::_1, mpl::_2, mpl::_3, mpl::_4>::type >, T>::type member_types;

    typedef typename mpl::transform<member_types, mpl::sizeof_<mpl::_1> >::type member_sizes;
    typedef typename mpl::accumulate<member_sizes, mpl::int_<0>, mpl::plus<mpl::_1, mpl::_2> >::type sum;
    return sum();
}

BOOST_FUSION_DEFINE_STRUCT(
    (), Foo_t,
    (std::uint8_t,  a)
    (std::uint16_t, b)
    (std::uint32_t, c)
    (std::uint64_t, d)
);
static_assert(sizeof_members<struct Foo_t>() == 15);

int main()
{
    std::cout << "sizeof_members = " << sizeof_members<struct Foo_t>() << std::endl;
    std::cout << "sizeof = " << sizeof(struct Foo_t) << std::endl;

    return 0;
}
sizeof_members<struct Foo_t>() = 15
sizeof(struct Foo_t) = 16
struct Foo_t {
    BOOST_HANA_DEFINE_STRUCT(Foo_t,
        (std::uint8_t, a),
        (std::uint16_t, b),
        (std::uint32_t, c),
        (std::uint64_t, d)
    );
};