Boost Fusion:在编译时验证适应的结构成员顺序 [英] Boost Fusion: validate adapted struct member ordering at compile time

查看:141
本文介绍了Boost Fusion:在编译时验证适应的结构成员顺序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 BOOST_FUSION_ADAPT_STRUCT(),我需要检查所有成员的声明方式和顺序是否正确。因此,我首先这样做:

I'm using BOOST_FUSION_ADAPT_STRUCT(), and I need to check that all the members are declared and in the correct order. So first I did this:

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()中):

Next I want to make sure the order is correct, so for example (x, z, y) in the above example should fail to compile. But so far I've only figured out a runtime solution (added to 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;
    }
};

但是我宁愿有一个编译时解决方案。你能想到一个吗?

But I'd rather have a compile-time solution. Can you think of one?

有趣的是,如果我有<$ c $,GCC实际上能够在编译时弄清楚会引发异常的地方c> -Wsuggest-attribute = noreturn -它告诉我何时调用 check()的函数不会返回(由于 logic_error )。

The funny thing is that GCC is actually able to figure out at compile time when an exception will be thrown, if I have -Wsuggest-attribute=noreturn - it tells me when a function which calls check() would not return (due to the logic_error).

如果您想自己尝试,相关标题为:

If you want to try it yourself, the relevant headers are:

#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>


推荐答案

此处以ms的答案为灵感,使用Boost.MPL而不是 std :: make_index_sequence<> 的解决方案,部分原因是我更习惯于这种样式:

Using m.s.'s answer here as inspiration, I drew up a solution using Boost.MPL instead of std::make_index_sequence<>, partly because I'm more accustomed to this style:

typedef mpl::range_c<unsigned, 0, fusion::result_of::size<Sequence>::value - 1> IndicesWithoutLast;
mpl::for_each<IndicesWithoutLast>(struct_offset_checker<Sequence>());

使用此仿函数:

template <typename Sequence>
struct struct_offset_checker
{
    template <typename Index>
    constexpr void operator()(Index)
    {
        typedef typename mpl::plus<Index, mpl::int_<1>>::type NextIndex;

        constexpr Sequence* dummy = nullptr;
        constexpr void* curr = &fusion::at<Index>(*dummy);
        constexpr void* next = &fusion::at<NextIndex>(*dummy);
        static_assert(curr < next, "fields are out of order");
    }
};

这篇关于Boost Fusion:在编译时验证适应的结构成员顺序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆