我正在尝试使用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/