Boost Fusion:在编译时验证调整后的结构成员排序

2024-01-28

我在用着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;
    }
};

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

有趣的是,GCC 实际上能够在编译时计算出何时抛出异常,如果我有的话-Wsuggest-attribute=noreturn- 它告诉我函数何时调用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>

为了执行编译时检查,您可以在constexpr使用调整序列的方式std::index_sequence:

#include <boost/fusion/adapted.hpp>
#include <boost/fusion/include/at.hpp>

struct foo
{
    char c;
    int x;
    float y;
    double z;
};


BOOST_FUSION_ADAPT_STRUCT(foo, x, c, y, z)

template <typename Sequence>
struct check_order
{
    template <std::size_t First, std::size_t Second>
    static constexpr bool internal()
    {
        constexpr Sequence* s = nullptr;
        const void* first = &boost::fusion::at_c<First>(*s);
        const void* second = &boost::fusion::at_c<Second>(*s);
        if (second <= first)
        {
            throw std::logic_error("struct member is declared in a different order");
        }
        return true;
    }

    template <std::size_t... Is>
    static constexpr bool run(std::index_sequence<Is...>)
    {
        int list[] = {(internal<Is,Is+1>(),0)...};
        (void)list;
        return true;
    }

    static constexpr void check()
    {
        constexpr std::size_t size = boost::fusion::result_of::size<Sequence>::type::value;
        static_assert(run(std::make_index_sequence<size-1>{}), "");
    }
};


int main()
{
    check_order<foo>::check();
}

根据需要,这失败了:

main.cpp: In instantiation of 'static constexpr void check_order<Sequence>::check() [with Sequence = foo]':
main.cpp:49:23:   required from here
main.cpp:42:9: error: non-constant condition for static assertion
         static_assert(run(std::make_index_sequence<size-1>{}), "");
         ^~~~~~~~~~~~~
main.cpp:42:26:   in constexpr expansion of 'check_order<Sequence>::run<{0ul, 1ul, 2ul}>((std::make_index_sequence<3ul>{}, std::make_index_sequence<3ul>()))'
main.cpp:34:41:   in constexpr expansion of 'check_order<Sequence>::internal<0ul, 1ul>()'

活生生的例子 http://coliru.stacked-crooked.com/a/5a000c56c748f02c

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Boost Fusion:在编译时验证调整后的结构成员排序 的相关文章

  • UTF8/UTF16 和 Base64 在编码方面有什么区别

    In c 我们可以使用下面的类来进行编码 System Text Encoding UTF8 System Text Encoding UTF16 System Text Encoding ASCII 为什么没有System Text En
  • 创建 DirectoryEntry 实例以供测试使用

    我正在尝试创建 DirectoryEntry 的实例 以便可以使用它来测试将传递 DirectoryEntry 的一些代码 然而 尽管进行了很多尝试 我还是找不到实例化 DE 并初始化它的 PropertyCollection 的方法 我有
  • 属性对象什么时候创建?

    由于属性实际上只是附加到程序集的元数据 这是否意味着属性对象仅根据请求创建 例如当您调用 GetCustomAttributes 时 或者它们是在创建对象时创建的 或者 前两个的组合 在由于 CLR 的属性扫描而创建对象时创建 从 CLR
  • C++:无法使用scoped_allocator_adaptor传播polymorphic_allocator

    我有一个vector
  • C# 中值类型和引用类型有什么区别? [复制]

    这个问题在这里已经有答案了 我知道一些差异 值类型存储在堆栈上 而引用类型存储在托管堆上 值类型变量直接包含它们的值 而引用变量仅包含对托管堆上创建的对象位置的引用 我错过了任何其他区别吗 如果是的话 它们是什么 请阅读 堆栈是一个实现细节
  • 跨多个控件共享事件处理程序

    在我用 C 编写的 Windows 窗体应用程序中 我有一堆按钮 当用户的鼠标悬停在按钮上时 我希望按钮的边框发生变化 目前我有以下多个实例 每个按钮一个副本 private void btnStopServer MouseEnter ob
  • 如何针对 Nancy 中的 Active Directory 进行身份验证?

    这是一篇过时的文章 但是http msdn microsoft com en us library ff650308 aspx paght000026 step3 http msdn microsoft com en us library
  • c# Asp.NET MVC 使用FileStreamResult下载excel文件

    我需要构建一个方法 它将接收模型 从中构建excel 构建和接收部分完成没有问题 然后使用内存流导出 让用户下载它 不将其保存在服务器上 我是 ASP NET 和 MVC 的新手 所以我找到了指南并将其构建为教程项目 public File
  • 当 Cortex-M3 出现硬故障时如何保留堆栈跟踪?

    使用以下设置 基于 Cortex M3 的 C gcc arm 交叉工具链 https launchpad net gcc arm embedded 使用 C 和 C FreeRtos 7 5 3 日食月神 Segger Jlink 与 J
  • 按字典顺序对整数数组进行排序 C++

    我想按字典顺序对一个大整数数组 例如 100 万个元素 进行排序 Example input 100 21 22 99 1 927 sorted 1 100 21 22 927 99 我用最简单的方法做到了 将所有数字转换为字符串 非常昂贵
  • 我的 strlcpy 版本

    海湾合作委员会 4 4 4 c89 我的程序做了很多字符串处理 我不想使用 strncpy 因为它不会终止 我不能使用 strlcpy 因为它不可移植 只是几个问题 我怎样才能让我的函数正常运行 以确保它完全安全稳定 单元测试 这对于生产来
  • 初始化变量的不同方式

    在 C 中初始化变量有多种方法 int z 3 与 int 相同z 3 Is int z z 3 same as int z z 3 您可以使用 int z z 3 Or just int z 3 Or int z 3 Or int z i
  • 将应用程序从 Microsoft Access 迁移到 VB 或 C#.NET

    我目前正试图说服管理层需要将我们的应用程序之一移植到 NET 该应用程序已经发展成为 Access 中的一个庞然大物 SQL 后端 拥有 700 个链接表 650 个表单 子表单 130 个模块和 850 个查询 我几乎知道这样做的所有主要
  • ListDictionary 类是否有通用替代方案?

    我正在查看一些示例代码 其中他们使用了ListDictionary对象来存储少量数据 大约 5 10 个对象左右 但这个数字可能会随着时间的推移而改变 我使用此类的唯一问题是 与我所做的其他所有事情不同 它不是通用的 这意味着 如果我在这里
  • 方法参数内的变量赋值

    我刚刚发现 通过发现错误 你可以这样做 string s 3 int i int TryParse s hello out i returns false 使用赋值的返回值是否合法 Obviously i is but is this th
  • 窗体最大化时自动缩放子控件

    有没有办法在最大化屏幕或更改分辨率时使 Windows 窗体上的所有内容自动缩放 我发现手动缩放它是正确的 但是当切换分辨率时我每次都必须更改它 this AutoScaleDimensions new System Drawing Siz
  • 如何在 C# 中播放在线资源中的 .mp3 文件?

    我的问题与此非常相似question https stackoverflow com questions 7556672 mp3 play from stream on c sharp 我有音乐网址 网址如http site com aud
  • 更改显示的 DPI 缩放大小使 Qt 应用程序的字体大小渲染得更大

    我使用 Qt 创建了一些 GUI 应用程序 我的 GUI 应用程序包含按钮和单选按钮等控件 当我运行应用程序时 按钮内的按钮和字体看起来正常 当我将显示器的 DPI 缩放大小从 100 更改为 150 或 200 时 无论分辨率如何 控件的
  • 如何连接字符串和常量字符?

    我需要将 hello world 放入c中 我怎样才能做到这一点 string a hello const char b world const char C string a hello const char b world a b co
  • 为什么 strtok 会导致分段错误?

    为什么下面的代码给出了Seg 最后一行有问题吗 char m ReadName printf nRead String s n m Writes OK char token token strtok m 如前所述 读取字符串打印没有问题 但

随机推荐