Boost.Fusion运行时开关

2024-03-14

我正在从文件中读取对象的类型:

enum class type_index { ... };
type_index typeidx = read(file_handle, type_index{});

根据类型索引,我想创建一个类型(从可能类型的列表中),并用它做一些通用的事情(每种类型使用相同的通用代码):

std::tuple<type1, type2, ..., typeN> possible_types;

boost::fusion::for_each(possible_types, [&](auto i) {
  if (i::typeidx != typeidx) { return; }
  // do generic stuff with i
});

That is:

  • 我对不同类型有相同的通用代码,
  • 我希望编译器为每种类型生成特定的代码,
  • 我只知道运行时需要哪种类型,并且
  • 我只想执行该单一类型的代码。

这感觉就像一个switch带有运行时条件的语句,但“情况”是在编译时生成的。特别是,这感觉不像for_each根本没有声明(我没有对向量、元组、列表中的所有元素执行任何操作,而只对单个元素执行任何操作)。

有没有更好更清晰的方式来表达/写这个成语? (例如,使用mpl::vector代替std::tuple对于可能的类型,使用与for_each算法,...)


我喜欢我常用的继承 lambda 技巧:

我以前写过这个

  • Lambda 函数作为基类 https://stackoverflow.com/questions/18432260/lambda-functions-as-base-classes/18432618#18432618
  • 在 C++ 中以不同方式处理多个输入命令的正确方法是什么? https://stackoverflow.com/questions/17768152/what-is-the-correct-way-to-handle-multiple-input-command-differently-in-c/17776618#17776618(它访问一个成员boost::variant)

我相信我已经看到 Sumant Tambe 在他最近的作品中使用了它cpptruths.com发帖。


示范

现在有一个演示。稍后会添加一些解释。

应用的最重要的技巧是我使用boost::variant为我们隐藏类型代码枚举。但即使您保留自己的类型区分逻辑(只需要更多编码),该原则也适用

Live On Coliru http://coliru.stacked-crooked.com/a/753ffd26c25a778d

#include <boost/serialization/variant.hpp>
#include <boost/serialization/vector.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/archive/text_oarchive.hpp>

#include <fstream>
#include <iostream>

using namespace boost; // brevity

//////////////////
// This is the utility part that I had created in earlier answers:
namespace util {
    template<typename T, class...Fs> struct visitor_t;

    template<typename T, class F1, class...Fs>
    struct visitor_t<T, F1, Fs...> : F1, visitor_t<T, Fs...>::type {
        typedef visitor_t type;
        visitor_t(F1 head, Fs...tail) : F1(head), visitor_t<T, Fs...>::type(tail...) {}

        using F1::operator();
        using visitor_t<T, Fs...>::type::operator();
    };

    template<typename T, class F> struct visitor_t<T, F> : F, boost::static_visitor<T> {
        typedef visitor_t type;
        visitor_t(F f) : F(f) {}
        using F::operator();
    };

    template<typename T=void, class...Fs>
    typename visitor_t<T, Fs...>::type make_visitor(Fs...x) { return {x...}; }
}

using util::make_visitor;

namespace my_types {
    //////////////////
    // fake types for demo only
    struct A1 {
        std::string data;
    };

    struct A2 {
        double data;
    };

    struct A3 {
        std::vector<int> data;
    };

    // some operations defined on A1,A2...
    template <typename A> static inline void serialize(A& ar, A1& a, unsigned) { ar & a.data; } // using boost serialization for brevity
    template <typename A> static inline void serialize(A& ar, A2& a, unsigned) { ar & a.data; } // using boost serialization for brevity
    template <typename A> static inline void serialize(A& ar, A3& a, unsigned) { ar & a.data; } // using boost serialization for brevity

    static inline void display(std::ostream& os, A3 const& a3) { os << "display A3: " << a3.data.size() << " elements\n"; }
    template <typename T> static inline void display(std::ostream& os, T const& an) { os << "display A1 or A2: " << an.data << "\n"; }

    //////////////////
    // our variant logic
    using AnyA = variant<A1,A2,A3>;

    //////////////////
    // test data setup
    AnyA generate() { // generate a random A1,A2...
        switch (rand()%3) {
            case 0: return A1{ "data is a string here" };
            case 1: return A2{ 42 };
            case 2: return A3{ { 1,2,3,4,5,6,7,8,9,10 } };
            default: throw std::invalid_argument("rand");
        }
    }

}

using my_types::AnyA;

void write_archive(std::string const& fname) // write a test archive of 10 random AnyA
{
    std::vector<AnyA> As;
    std::generate_n(back_inserter(As), 10, my_types::generate);

    std::ofstream ofs(fname, std::ios::binary);
    archive::text_oarchive oa(ofs);

    oa << As;
}

//////////////////
// logic under test
template <typename F>
void process_archive(std::string const& fname, F process) // reads a archive of AnyA and calls the processing function on it
{
    std::ifstream ifs(fname, std::ios::binary);
    archive::text_iarchive ia(ifs);

    std::vector<AnyA> As;
    ia >> As;

    for(auto& a : As)
        apply_visitor(process, a);
}

int main() {
    srand(time(0));

    write_archive("archive.txt");

    // the following is c++11/c++1y lambda shorthand for entirely compiletime
    // generated code for the specific type(s) received
    auto visitor = make_visitor(
        [](my_types::A2& a3) { 
                std::cout << "Skipping A2 items, just because we can\n";
                display(std::cout, a3);
            },
        [](auto& other) { 
                std::cout << "Processing (other)\n";
                display(std::cout, other);
            }
        );

    process_archive("archive.txt", visitor);
}

Prints

Processing (other)
display A3: 10 elements
Skipping A2 items, just because we can
display A1 or A2: 42
Processing (other)
display A1 or A2: data is a string here
Processing (other)
display A3: 10 elements
Processing (other)
display A1 or A2: data is a string here
Processing (other)
display A1 or A2: data is a string here
Processing (other)
display A3: 10 elements
Processing (other)
display A1 or A2: data is a string here
Processing (other)
display A3: 10 elements
Processing (other)
display A3: 10 elements
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Boost.Fusion运行时开关 的相关文章

  • 语言混合:模型和视图

    考虑开发一个应用程序 其中模型将使用 C 使用 Boost 编写 视图将使用 Objective C 使用 Cocoa Touch 编写 哪里有一些示例展示了如何集成 C 和 Objective C 来开发 iPhone 应用程序 直接从源
  • 如何使用 C# 打印 pdf

    我在 C 应用程序中使用 进程 打印 pdf 文件 但是我无法获取打印状态 我发现可以通过 System management 和 System printing 与打印机 队列进行交互 我做了很多尝试 但都出错了使用这两个命名空间但无法打
  • 从 .Net 将简单数据插入 Excel 文件的最简单方法

    我有一个 Excel 文件 大约有 10 列和 1 20 行 我需要插入 1 20 行包含各种数据元素 我想知道是否有一种方法可以将一些标签放入 Excel 文件中 以便可以找到并替换它们 将列标记为 名称 的东西 这样我就可以在代码中说
  • C++:获取注册表值仅给出第一个字符[重复]

    这个问题在这里已经有答案了 我试图从注册表中获取字符串值 但我只得到第一个字母 HKEY hKey char gamePath MAX PATH if RegOpenKeyEx HKEY CURRENT USER L Software Bl
  • 当我尝试使用 AVX 功能时,Clang 生成错误

    我使用的是 Windows 10 使用 Clang 版本 5 最近安装 当我编译以下内容时 define AVX define AVX2 include
  • 将占位符文本添加到文本框

    我正在寻找一种将占位符文本添加到文本框的方法 就像在 html5 中使用文本框一样 IE 如果文本框没有文本 则会添加文本Enter some text here 当用户单击它时 占位符文本消失并允许用户输入自己的文本 如果文本框失去焦点并
  • 实体框架7审计日志

    我正在将一个旧项目移植到 ASP NET 5 和 Entity Framework 7 我使用数据库优先方法 DNX 脚手架 来创建模型 旧项目基于Entity Framework 4 审计跟踪是通过重写实现的SaveChanges的方法D
  • Windows 程序如何临时更改其时区?

    我写了一个函数来返回time t与给定日期的午夜相对应的值 当给定日期没有午夜时 它返回最早可用的时间 例如 当埃及进入夏令时时 这种情况就可能发生 今年 时间更改于 4 月 29 日晚上午夜生效 因此时钟直接从 23 59 转到 01 0
  • Type_traits *_v 变量模板实用程序顺序无法编译

    看过了这个答案 https stackoverflow com a 31763111 7151494 我试图想出一个变量模板从中获取代码的实用程序 template
  • 使用 Microsoft Graph 创建用户

    如何使用 Microsoft graph 创建用户 因为我在保存过程中遇到了权限失败的问题 我确实有几个问题 在图中调用创建用户 API 将在哪里创建用户 是在 Azure AD 还是其他地方 我尝试通过传递 json 和必需的标头来调用创
  • ASP MVC 5 - 403 customError 不起作用

    我正在尝试为我的应用程序创建自定义错误页面 它在大部分情况下都有效 但不适用于403 errors 我的网络配置
  • 使用 cudamalloc()。为什么是双指针?

    我目前正在浏览有关的教程示例http code google com p stanford cs193g sp2010 http code google com p stanford cs193g sp2010 学习CUDA 演示的代码 g
  • 打破条件变量死锁

    我遇到这样的情况 线程 1 正在等待条件变量 A 该变量应该由线程 2 唤醒 现在线程 2 正在等待条件变量 B 该变量应该由线程 1 唤醒 在我使用的场景中条件变量 我无法避免这样的死锁情况 我检测到循环 死锁 并终止死锁参与者的线程之一
  • IEnumerable.比带中断的 for 循环更快吗?

    我们的代码打开表单时遇到了一些缓慢的情况 这可能是由于for循环与break这需要很长时间才能执行 我把它切换到IEnumerable Any 并看到表格很快打开 我现在试图弄清楚是否单独进行此更改会提高性能 或者是否正在访问Product
  • 如果数组为空,LINQ 返回 null

    public class Stuff public int x other stuff 我有一个IEnumerable
  • Unity 2.0 和处理 IDisposable 类型(特别是使用 PerThreadLifetimeManager)

    我知道类似的问题被问过好几次 例如 here https stackoverflow com questions 987761 how do you reconcile idisposable and ioc here https stac
  • 向每个收件人发送一封包含不同内容的电子邮件(使用抄送字段)

    在你因为这个问题 毫无意义 和 不可能 而驳回之前 请听我说完 问题 我们在使用我们的系统发送的每封电子邮件中实施跟踪像素 即具有唯一 URL 的可下载 GIF 文件 这有助于我们跟踪电子邮件的打开情况 问题是 当我们抄送一些收件人时 跟踪
  • Intel 和 AMD 处理器有相同的汇编程序吗?

    C语言被用来编写Unix以实现可移植性 使用不同编译器编译的同一个C语言程序会产生不同的机器指令 为什么 Windows 操作系统能够在两者上运行Intel https en wikipedia org wiki Intel and AMD
  • C 中的静态和动态绑定(严格来说是 C,而不是 C++)是什么?

    我最初对发布这个问题感到担忧 以免它重复 但即使在谷歌搜索了许多关键字之后 我在 StackOverflow 上找不到任何解释 C 的静态和动态绑定的链接 尽管有 C 的问题和答案 但是都涉及classes以及显然不适合 C 的东西 Sta
  • 如何设置 Swashbuckle 与 Microsoft.AspNetCore.Mvc.Versioning

    我们有asp net core webapi 我们添加了Microsoft AspNetCore Mvc Versioning and Swashbuckle拥有招摇的用户界面 我们将控制器指定为 ApiVersion 1 0 Route

随机推荐

  • 动态增加列表视图中的元素数量

    我想增加列表视图滚动到末尾时动态显示的项目数量 就我而言 我的列表视图最初将显示 10 个项目 然后 当我们滚动到最后一个项目时 它必须开始显示另外 10 个项目 依此类推 我怎样才能做到这一点 这是我的自定义阵列适配器 package c
  • 无法理解“选项卡”。

    我正在读 C 编程语言 我无法理解第 34 页的练习 1 20 编写一个程序 detab 用适当数量的空格替换输入中的制表符 以分隔到下一个制表位 假设有一组固定的制表位 例如每 n 列 n 应该是变量还是符号参数 第二句话我不明白 让我们
  • Apple Watch 应用程序的 Xcode 7 安装从未完成

    我想尝试一下新的 Apple Watch OS2 打开我现有的项目 添加了目标 更改了捆绑包标识符以删除错误消息 手表应用程序永远不会启动 大约 5 分钟后 我在 Xcode 中收到此错误消息 我还没有添加任何 Swift 代码 我所做的就
  • ZipPackage 类与 Zipfile 类

    我对这两个类感到困惑 它们似乎都用于创建或提取 zip 文件 谁能解释其中的区别吗 ZipPackage Class 实现抽象 Package 基类的派生子类 ZipPackage 类使用 ZIP 存档作为容器存储 这个类不能被继承 Zip
  • DatagridView 如何让每列有不同的行数?

    所以我试图以特定格式显示我的数据datagridview 所以我的格式是这样的 A B C 1 1 1 2 2 x 3 x x x 表示没有单元格 正如您所看到的 每列都有不同的行数 我想在 DatagridView 或 Dot Net F
  • 如何修复错误 - 创建新 Google 表格时参数无效:file.contentType

    我正在尝试在已创建的文件夹中创建新的 Google 表格 但内容类型存在问题 我已经搜索过这个错误 但没有找到任何东西 大多数搜索都会出现MimeType错误 但我不认为这是问题所在 下面是我正在使用的代码 var ss Spreadshe
  • 处理本地化字符串包含单个 TextView 中的链接

    我的 strings xml 文件中有一个字符串 单击该字符串的某些部分会重定向到任务 该部分是根据字符串的索引制作的 现在我正在尝试将其翻译为法语 但我遇到了索引越界异常 因为它的长度小于英语字符串的长度 谁能说一下 处理这种情况的最佳方
  • 如何在Python中调用带有两个参数的函数

    我想问一下如何在 python 中调用带有两个参数的函数 例如 下面的代码是我想调用颜色函数的示例 def color object return 033 1 34m object 033 1 m tes this must be blue
  • 没有公钥的 EF 实体

    我想在 EF 中创建一个没有公钥的实体 支持表具有非唯一的聚集键 但表中的数据从概念上讲没有可以使用的唯一主键 看来EF确实不喜欢这样 有没有什么方法可以让 EF 接受该表没有主键并使其可以使用它 而不会影响性能 我不在乎结果是否是只读的
  • 当 php://temp 多次打开时会发生什么?

    If the php temp or php memory 文件被打开多次 句柄是否会指向同一个文件 或者每个手柄都是独一无二的 我在 php 文档中找不到答案 所以我要去编写一个测试脚本来找出答案 https stackoverflow
  • 将新 ns 映射到旧 ns

    我将 Android Studio 更新到 4 2 1 并删除了 jcentor 在构建项目时出现了这样的警告 我不明白这些 URL 的含义以及如何修复它 映射新的nshttp schemas android com repository
  • Flask 在文件上传时出现错误 400

    我有以下内容
  • 如何在我的发布 aar 中打包多个 AAR

    我们向客户发送 android sdk aar 文件 我们的代码在内部使用我们的存储库中的两个第三方 aar 并且 gradle 在运行时引用它 我的问题是如何将这些依赖项发送给客户 就好像如果我不想给他们那些第 3 方 aar 我怎样才能
  • 如何通过闪亮的按钮动态添加/删除输入字段

    我一直在尝试找到一种解决方案 如何使用闪亮的按钮添加和删除输入字段 我没有源代码 因为我还没有取得太大进展 但是这个 jQuery 示例 http www mkyong com jquery how to add remove textbo
  • 迁移到.net core 3.1后EF OrderBy出现问题

    考虑这段代码 dbContext Messages GroupBy m gt new MinId m SenderId lt m RecipientId m SenderId m RecipientId MaxId m SenderId g
  • 用g++编译简单的SDL程序时找不到-lSDLmain和-lSDL

    我使用 mingw 安装了 SDL2this http lazyfoo net SDL tutorials lesson01 windows mingw index php指导 但是 当我尝试使用他们提供的编译语法和测试代码进行编译时 仅使
  • java JNI 错误 java.lang.UnsatisfiedLinkError:

    java Djava library path TestJNI gt gt gt gt Exception in thread main java lang UnsatisfiedLinkError TestJNI calibrate D
  • 如何配置 GroovyConsole 以便我不必在启动时导入库?

    我有一个使用第三方库的常规脚本 每次我打开应用程序并尝试运行我的脚本时 我都必须导入正确的库 我希望能够打开 GroovyConsole 并运行我的应用程序 而无需导入库 在 Linux 中你也有 usr share groovy conf
  • NSString stringWithFormat 问题

    我正在尝试使用 NSString 构建一个小表 我似乎无法正确格式化字符串 这是我所拥有的 NSString stringWithFormat 8 6f e v 其中 e 是来自其他地方的 NSString v 是浮点数 我想要的是输出类似
  • Boost.Fusion运行时开关

    我正在从文件中读取对象的类型 enum class type index type index typeidx read file handle type index 根据类型索引 我想创建一个类型 从可能类型的列表中 并用它做一些通用的事