结构减去填充的编译时大小
Compile-time Size of Struct Minus Padding
我正在尝试使用 Boost MPL 和 Fusion 来计算不包括任何填充的结构的大小。这是我目前最好的尝试:
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
是一个接受对象和 returns 该成员的函数。
Demo.
我正在尝试使用 Boost MPL 和 Fusion 来计算不包括任何填充的结构的大小。这是我目前最好的尝试:
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
是一个接受对象和 returns 该成员的函数。
Demo.