【发布时间】:2016-09-29 05:30:58
【问题描述】:
我正在使用BOOST_FUSION_ADAPT_STRUCT(),我需要检查所有成员是否已声明且顺序正确。所以首先我这样做了:
template <typename Sequence>
struct checker
{
static void check()
{
typedef typename mpl::accumulate<Sequence, mpl::size_t<0>,
mpl::plus<mpl::_1, mpl::sizeof_<mpl::_2>>>::type total_size;
static_assert(sizeof(Sequence) == total_size::value, "omitted field?");
}
};
这行得通:
struct foo
{
int x;
float y;
double z;
};
BOOST_FUSION_ADAPT_STRUCT(foo, x, y, z);
checker<foo>::check(); // fails if any field is missing
接下来我要确保顺序正确,例如上面示例中的(x, z, y) 应该无法编译。但到目前为止我只想出了一个运行时解决方案(添加到check()):
const Sequence* dummy = nullptr;
++dummy;
boost::fusion::for_each(*dummy, struct_offset_checker());
使用这个函子:
struct struct_offset_checker
{
mutable const void* _last = nullptr;
template <typename Element>
void operator()(const Element& element) const
{
if (&element <= _last)
throw std::logic_error("struct member is declared in a different order");
_last = &element;
}
};
但我宁愿有一个编译时解决方案。你能想到一个吗?
有趣的是,如果我有-Wsuggest-attribute=noreturn,GCC 实际上能够在编译时确定何时会引发异常——它告诉我调用check() 的函数何时不会返回(由于logic_error)。
如果你想自己尝试,相关的标题是:
#include <stdexcept>
#include <boost/fusion/adapted.hpp>
#include <boost/mpl/accumulate.hpp>
#include <boost/mpl/plus.hpp>
#include <boost/mpl/sizeof.hpp>
#include <boost/mpl/size_t.hpp>
【问题讨论】:
-
您的遗漏检查没有考虑到填充 - coliru.stacked-crooked.com/a/88ff885041f95349
-
您使用的是哪个 C++ 标准?你能用 C++11 还是 C++14 吗?
-
@m.s.:我使用的是 C++14。
-
@Praetorian:是的,我知道。没关系,我也不想接受填充结构。实际上,当存在填充时它会失败。
标签: c++ template-meta-programming boost-mpl static-assert boost-fusion