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

标签 c++ c++17 boost-mpl compile-time-constant boost-fusion

我正在尝试使用Boost MPL和Fusion来计算不包含任何填充的结构的大小。这是我目前的最佳尝试:

Live example

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

我可以将类型的序列转换为包含每种类型的大小的整数序列,并且可以计算该序列的总和,但是在将结构转换为类型的序列的第一步中遇到了麻烦。 Fusion文档说BOOST_FUSION_DEFINE_STRUCT生成样板,以定义和改编任意结构作为随机访问序列模型,我认为它应该与mpl::transform兼容,但是似乎缺少一些粘合代码这项工作。我当前使用mpl::unpack_args的方法有效,但仅适用于具有四个字段的结构。

如何将其扩展到具有更多或更少字段的任意结构?

最佳答案

由于您标记了此C++ 17,因此答案是:不要使用Boost.MPL。即使是C++ 11,您想要的元编程库也是Boost.Mp11-在所有方面都要好得多。

您想要使用的Boost.Fusion的更新,更易于使用,可笑的是编译时间效率更高的版本是Boost.Hana:

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)
    );
};

之所以要使用Boost.Hana是因为sizeof_members(对于任何数量的成员)都可以写成:

template <typename T>
constexpr auto sizeof_members() -> size_t
{
    return hana::fold(hana::accessors<T>(), size_t{},
        [](size_t s, auto mem){
            return s + sizeof(hana::second(mem)(std::declval<T>()));
        });
}

static_assert(sizeof_members<Foo_t>() == 15);

这大致上与您实际想要执行的操作完全相同:您想折叠所有成员(从0开始),并具有一个累加函数,该函数会增加下一个成员的大小(accessors<T>()为您提供了一个成对的序列,其中first是访问器的名称和second是一个接受对象并返回该成员的函数。

Demo

关于c++ - 结构减去填充的编译时大小,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62148977/

相关文章:

c++ - 非递归获取可变参数模板最后类型的通用类型特征?

c++ - 使用 boost::mpl 的类型列表的排列

c++ - mfc - 带有自定义参数的发送消息/邮寄消息

c++ - 如何将我的程序指向我输入到列表中的值? C++

c++ - 将二进制文件添加到其他人的柯南食谱中

c++ - 结构化绑定(bind)和 tie()

c++ - 如何将 C++ range-v3 输出到 ostringstream?

c++ 模板:boost::mpl::transform with template 模板参数

c++ - 用 C++17 功能替换 Boost MPL 容器

c++ - 为两个相似的类定义一次成员函数?