我可以读取文件并在编译时构造异构对象吗?

2024-01-01

情况:

YAML 文件包含按名称排列的异构对象列表,如下所示:

object: Foo
  name: Joe Bloggs
  age: 26
object: Bar
  location: UK

对象不继承任何基类,也不共享彼此之间的任何类型的关系,除了它们看起来“生活”在一起的事实之外。

它可以包含任意数量的对象。如果需要,可用类型的列表可以存在于代码库的类型列表中。

在我的 C++ 土地上,我有以下对象:

struct Foo {
  Foo(std::string n, int a) : name(n), age(a) {}

  std::string name;
  int age;
};

struct Bar {
  Bar(std::string l) : location(l) {}

  std::string location;
};

在编译时,我想将该 YAML 文件转换为boost::fusion::vector:

boost::fusion::vector<Foo, Bar>(Foo("Joe Bloggs", 26), Bar("UK"));

Or:

boost::fusion::vector<Foo, Bar>(make_obj<Foo>("Joe Bloggs", 26), make_obj<Bar>("UK"));

也可以是一个std::tuple如果它让生活更轻松的话。

如果需要,所有受支持的对象都可以存在 make_obj 的特化。

这可能吗?

如果需要的话,愿意亲自参与 MPL/其他高级元编程,或者,我可以使用 constexpr 完成所有这些工作吗?

C++ 版本不用担心,如果需要可以使用 trunk Clang C++14。


我看到两种主要方法:

使用编译时“反射”

您可以使用 BOOST_FUSION_ADAPT_STRUCT 并鱼与熊掌兼得。如果你调整你的结构,你可以静态地迭代它们 - 事实上编写 @πάνταῥεῖ 提到的代码生成器,但与 C++ 代码内联并在编译时。

您可以使用变体对类型进行静态约束。

  • 是否可以从适应的结构生成融合图? https://stackoverflow.com/questions/19657065/is-it-possible-to-generate-a-fusion-map-from-an-adapted-struct/19658340#19658340显示如何使用fusion::extension::struct_member_name转储适应 Fusion 的通用结构(您可以忘记类型名称分解,因为您不需要它)
  • 增强结构和类的融合序列类型和名称识别 https://stackoverflow.com/questions/26380420/boost-fusion-sequence-type-and-name-identification-for-structs-and-class/26381145#26381145显示 Fusion 适应结构的类似 XML 的输出。

附有语法手册

使用 Boost Spirit,您可以为相同的结构创建语法:

    start   = *(label_(+"object") >> object_);
    object_ = foo_ | bar_;

    foo_    = "Foo" >> eol >> (
                (string_prop_(+"name") >> eol) ^
                (int_prop_(+"age") >> eol)
            );

    bar_    = "Bar" >> eol >> (
                (string_prop_(+"location") >> eol)
            );

    label_  = lit(_r1) >> ':';

    string_prop_ = label_(_r1) >> lexeme [ *(char_ - eol) ];
    int_prop_    = label_(_r1) >> int_;

现在这解析成variant<Foo, Bar>无需任何进一步的编码。它甚至允许name and age以随机顺序出现(或接受默认值)。当然,如果你不这样做want这种灵活性,取代^ with >>在语法中。

这是一个示例输入:

object: Foo
  name: Joe Bloggs
  age: 26
object: Foo
  age: 42
  name: Douglas Adams
object: Foo
  name: Lego Man
object: Bar
  location: UK

这是示例(调试)输出的尾部:

<success></success>
<attributes>[[[[J, o, e,  , B, l, o, g, g, s], 26], [[D, o, u, g, l, a, s,  , A, d, a, m, s], 42], [[L, e, g, o,  , M, a, n], 0], [[U, K]]]]</attributes>
</start>
Parse success: 4 objects
N4data3FooE (Joe Bloggs 26)
N4data3FooE (Douglas Adams 42)
N4data3FooE (Lego Man 0)
N4data3BarE (UK)

Live On Coliru http://coliru.stacked-crooked.com/a/2a7b6bda0049aa7e

#define BOOST_SPIRIT_DEBUG
#define BOOST_SPIRIT_USE_PHOENIX_V3
#include <boost/spirit/include/qi.hpp>
#include <boost/fusion/adapted/struct.hpp>
#include <boost/bind.hpp>
#include <fstream>

namespace qi  = boost::spirit::qi;
namespace phx = boost::phoenix;

namespace demo {
    struct visitor : boost::static_visitor<> {
        template<typename Seq>
            void operator()(std::ostream& os, Seq const& seq) const {
                os << typeid(Seq).name() << "\t" << boost::fusion::as_vector(seq);
            }
    };
}

namespace data {
    struct Foo {
        Foo(std::string n="", int a=0) : name(n), age(a) {}

        std::string name;
        int age;
    };

    struct Bar {
        Bar(std::string l="") : location(l) {}

        std::string location;
    };

    using object  = boost::variant<Foo, Bar>;
    using objects = std::vector<object>;

    std::ostream& operator<< (std::ostream& os, object const& o) {
        boost::apply_visitor(boost::bind(demo::visitor(), boost::ref(os), _1), o);
        return os;
    }
}

BOOST_FUSION_ADAPT_STRUCT(data::Foo,(std::string,name)(int,age))
BOOST_FUSION_ADAPT_STRUCT(data::Bar,(std::string,location))

template <typename It>
struct grammar : qi::grammar<It, data::objects(), qi::blank_type> {
    grammar() : grammar::base_type(start) {
        using namespace qi;

        start   = *(label_(+"object") >> object_);
        object_ = foo_ | bar_;

        foo_    = "Foo" >> eol >> (
                    (string_prop_(+"name") >> eol) ^
                    (int_prop_(+"age") >> eol)
                );

        bar_    = "Bar" >> eol >> (
                    (string_prop_(+"location") >> eol)
                );

        label_  = lit(_r1) >> ':';

        string_prop_ = label_(_r1) >> lexeme [ *(char_ - eol) ];
        int_prop_    = label_(_r1) >> int_;

        BOOST_SPIRIT_DEBUG_NODES((start)(object_)(foo_)(bar_)(label_)(string_prop_)(int_prop_));
    }
  private:
    qi::rule<It, data::objects(), qi::blank_type> start;
    qi::rule<It, data::object(),  qi::blank_type> object_;
    qi::rule<It, data::Foo(),     qi::blank_type> foo_;
    qi::rule<It, data::Bar(),     qi::blank_type> bar_;

    qi::rule<It, std::string(std::string), qi::blank_type> string_prop_;
    qi::rule<It, int(std::string), qi::blank_type>         int_prop_;
    qi::rule<It, void(std::string), qi::blank_type>        label_;
};

int main()
{
    using It = boost::spirit::istream_iterator;
    std::ifstream ifs("input.txt");
    It f(ifs >> std::noskipws), l;

    grammar<It> p;
    data::objects parsed;
    bool ok = qi::phrase_parse(f,l,p,qi::blank,parsed);
    if (ok)
    {
        std::cout << "Parse success: " << parsed.size() << " objects\n";
        for(auto& object : parsed)
            std::cout << object << "\n";
    } else
    {
        std::cout << "Parse failed\n";
    }

    if (f!=l)
        std::cout << "Remaining unparsed input: '" << std::string(f,l) << "'\n";
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

我可以读取文件并在编译时构造异构对象吗? 的相关文章

  • 带有 Windows 窗体应用程序的地图

    我正在构建一个需要地图的 C Winforms 应用程序 例如 Google 地图 Bing 地图等 但我对 ToU 许可 非商业使用等感到非常困惑 我的问题 您建议将哪个地图提供商 最好是免费的 嵌入到 winforms 应用程序中以用于
  • 类变量在其定义范围内?

    这可能是一个愚蠢的问题 我正在尝试制作文本泥 我需要每个 Room 类包含其他 Room 类 以便在尝试移动到它们或从它们获取信息时可以引用 但是 我不能这样做 因为我显然无法在其定义中声明一个类 那么 我该怎么做呢 当我说我做不到时 我的
  • 在 std::forward 中它如何接受右值?

    看看斯科特 迈耶的有效的现代 C 第200 201页 建议的简化实施std forward可能是 在其他地方看到了正确的实现 template
  • C# - 如何从 Steam 交易 API 获取图标的 URL(编码)

    以下是 API 为每个项目返回的 XML 部分
  • C# 中 value 为匿名类型的字典

    是否可以在 C 中创建一个System Collections Generic Dictionary
  • flowlayoutpanel和水平滚动条问题

    我正在使用一个 flowlayoutpanel 它有很多逻辑上的按钮 我遇到的问题是 当我调整窗口大小时 当窗口变小时 我无法看到所有水平排列的按钮 相反 当窗口变小时 按钮会下降到下一行 谁能帮我解决这个问题 我只是希望按钮水平排列 当窗
  • 可以轻易移动,但不可轻易复制

    是否可以创建类类型 即 普通移动构造 但不是普通复制构造 但仍然可复制构造 普通复制构造 但不是普通移动构造 但仍然可移动构造 可以简单地复制分配 但不能简单地移动分配 但仍然可以移动分配 可以简单地移动分配 但不能简单地复制分配 但仍然可
  • WPF 中可选择的 TextBlock 或带有格式化文本的 TextBox

    我遇到一种情况 我需要显示格式化文本 正常 粗体 突出显示 并且还应该是可选择的 以便用户可以复制文本 我使用了文本块 我可以使用内联内容流元素应用多种格式 但不幸的是它的文本不可选择 虽然文本框允许选择文本并复制到剪贴板 但它不允许我设置
  • 有没有办法对 RichTextBox 的撤消历史进行分组或暂时禁用它?

    我目前正在研究 WPF 中 RichTextBox 内的表格 在 WPF 中 表格没有行和列 只有行 每行都有一定数量的单元格 当用户按下 添加列 按钮时 我的程序会向每一行添加一个新单元格 使用此方法的问题是 在用户添加一列后 如果他们按
  • Parallel ForEach 的本地初始化如何工作?

    我不确定 Parallel ForEach 中本地 init 函数的使用 如 msdn 文章中所述 http msdn microsoft com en us library dd997393 aspx http msdn microsof
  • 等效

    这是否保证始终为真 std numeric limits
  • 在 4.x 内核上的 64 位内存中查找系统调用表

    我正在尝试编写一个简单的内核模块来查找 Linux 中的 sys call table 但遇到了一些麻烦 我在这里找到了 32 位 Linux 的基本指南 https memset wordpress com 2011 03 18 sysc
  • 对嵌套属性使用 XmlAttributeOverrides

    我试图使用 XmlAttributeOverrides 来控制类序列化后哪些类属性出现在 xml 中 它适用于 根 类上的属性 但不适用于嵌套属性 这是一个简单的例子来说明我想要完成的任务 我的类层次结构如下 public class Ma
  • 为什么 istream/ostream 慢

    于 50 40http channel9 msdn com Events GoingNative 2013 Writing Quick Code in Cpp Quickly http channel9 msdn com Events Go
  • 如何设置扬声器声音增强设置

    如何以编程方式设置 Windows 扬声器设置 增强 选项卡 中可用的声音效果 恐怕这是不可能的 参见 Maurits 对他的评论blog http blogs msdn com b matthew van eerde archive 20
  • 所有区域的启用保护模式必须设置为相同的值(启用或禁用)

    我正在尝试使用Selenium Internet Explorer驱动程序 但当我尝试实例化它时它崩溃了 TestInitialize public void TestInitialise ieDriver new InternetExpl
  • 为 winforms ComboBox 中的单个项目着色?

    我遇到了一个困境 我有一个表单 其中包含许多组合框 其中包含在某些情况下可能无效 过时的信息 选项 项目 我不能简单地从项目中删除过时的信息 但我确实想在选项无效时为用户提供视觉线索 我正在考虑对项目进行着色 可能是红色 来指示它们是否无效
  • wpf中的图像问题(图像不显示)

    我不明白为什么我无法在 WPF 中显示图像 也许我不小心修改了我的资源文件夹 这就是我没有显示的原因 所以我创建了一个新的 wpf 应用程序 我有这个 当我运行该程序时 我的图片显示为 为什么当我尝试在程序中执行相同的操作时 图像没有显示
  • In 和 Out 属性在 .NET 中如何工作?

    我一直在尝试跨序列化数组AppDomain边界 使用以下代码 public int Read byte buffer int offset int count return base Read buffer offset count 作为猜
  • 如何获取打印机设备上下文?

    我在 Windows 上尝试使用以下命令打印增强型图元文件 EMF 播放增强元文件 http msdn microsoft com en us library dd162800 28VS 85 29 aspx 我当前正在使用屏幕上窗口的设备

随机推荐

  • C++ std::map 命名要求分配器感知容器

    目前我正在尝试将一些 C 的命名需求转换为 C 20 概念 https godbolt org z EdY5d6319 https godbolt org z EdY5d6319仍然处于高度WIP状态 然而 我遇到了一个问题 鉴于最终的 C
  • 使用文件“php.ini”关闭显示错误

    我正在尝试关闭我网站上的所有错误 我已经遵循了有关如何执行此操作的不同教程 但我不断收到阅读和打开错误消息 我有什么遗漏的吗 我在我的中尝试过以下操作php ini file Error display display startup er
  • SwiftUI 从另一个视图重新排序列表动态部分

    我有一个简单的List与存储在内部的部分ObservableObject 我想从另一个角度重新排序它们 这是我的代码 class ViewModel ObservableObject Published var sections S1 S2
  • 基本的 Spring Boot 应用程序无法正常工作,显示:无法从进程 xxxx 刷新实时数据

    我是 Spring Boot 的初学者 我初始化了一个新项目并尝试运行它 但它没有成功运行 当我将其作为 Spring Boot 应用程序运行时 它就会开始执行 在底部编译器 状态栏中 它显示处理和重试 它最多运行 10 次并抛出以下错误
  • C++ 中的十进制到 Unicode Char

    输出时如何将十进制数 例如 225 转换为其对应的 Unicode 字符 我可以将 ASCII 字符从十进制转换为如下字符 int a 97 char b a cout lt lt b lt lt endl 它输出字母 a 但当我使用数字
  • 在Python中将整数转换为十六进制

    在Python中我想转换整数3892转换为具有给定格式和结果的十六进制代码 x00 x00 x0F x34 如何才能实现这一目标 您正在转换为数字的二进制表示形式 而不是十六进制表示形式 尽管 Python 会将字节显示为十六进制 使用st
  • 尝试上传使用 Visual Studio for Apache Cordova 构建的应用程序时出现错误 ITMS-90161

    我们刚刚开始使用 Visual Studio Tools for Apache Cordova 创建跨平台移动应用程序 我按照中描述的程序进行操作安装 iOS 构建工具 https msdn microsoft com en us libr
  • 以 PHP 形式输入和验证自定义日期时间的最佳方法

    这是前端可用性和 PHP DATE TIME 验证方面的双重问题 我正在为一位客户开发一个网站 他想添加他完成项目的日期 以便项目可以按该顺序列出 他将是唯一使用管理界面的人 所以我希望它尽可能简单 我将日期作为 DATE TIME 存储在
  • 具有多个条件的数据表选择

    我有一个包含 4 列 A B C 和 D 的数据表 因此 A B 和 C 列的值的特定组合在数据表中是唯一的 客观的 对于给定的 A B 和 C 列值组合 查找 D 列的值 我想循环数据行集应该可以做到 有没有办法使用 Datatable
  • Docker BuildX 映像未显示在 docker image ls 中

    我目前正在尝试使用 BuildKit BuildX 构建多平台映像 x86 64 arm64 armv7 armv6 并且似乎构建成功 但我似乎找不到映像所在的位置 它与我之前的 x86 64 版本相比并没有显示出任何变化 并且当尝试码头工
  • 在 JavaScript 中,我如何使用数组来增加字符串以创建循环?

    我正在尝试制作一个网页 每次刷新时其壁纸都会发生变化 我希望它在每次刷新页面时显示数组中的下一个图像 因此 每次刷新都会遍历列表直至结束 然后重新开始 现在我正在使用一个数组并使用随机索引访问它 但我需要使用每次增加 1 的索引来访问它 一
  • iOS 8.4 CFNetwork SSL 握手失败 (-9850)

    自从我将 xcode 更新到 6 4 并将模拟器更新到 ios 8 4 后 我的 ssl 握手代码失败了 错误是 CFNetwork SSLHandshake 失败 9850 相同的代码在 ios 8 3 模拟器上成功执行 ssl 握手 我
  • 如何返回到控制台中行的开头?

    如何返回到行的开头并覆盖控制台上已输出的内容 以下似乎不起作用 System out print mystuff r 我怀疑您的光标正在移动到该行的前面 您已有的文本不会消失 因为您没有用任何内容覆盖它 您可以输出空格来空白该行 然后添加另
  • 无法读取 Web API 操作过滤器内容

    相关问题 Web API 操作参数间歇性为空 https stackoverflow com questions 18256817 web api action parameter is intermittently null and ht
  • GDB 报告 c++ 对象构造函数中参数的地址错误

    我遇到了 GDB 将字符串作为参数传递给构造函数的奇怪行为 代码工作正常 但是当我在调试器中单步执行时 GDB 似乎认为我的参数位于不同的地址 有谁知道这是怎么回事 这是我可以创建的最简单的程序来演示该问题 jwcacces neptune
  • Spring Boot 集成测试不读取属性文件

    我想创建集成测试 其中 Spring Boot 将使用从 properties 文件读取值 Value注解 但每次我运行测试时 我的断言都会失败 因为 Spring 无法读取该值 org junit ComparisonFailure Ex
  • 如何在 Outlook 签名中嵌入图像?

    是否可以为以下内容创建 HTML 电子邮件签名 2003年展望或上面不引用外部图像 也就是说 使用那些特殊的 cid 引用 但将图像本身嵌入到签名中 而不是嵌入到文件系统或网络中 这是一个 Web 应用程序 它根据用户的各种输入生成 标准
  • 使用 javascript 中的类加载 php 页面

    我在 javascript 中有弹出类 并在我的 html 页面中添加了显示该弹出窗口所需的所有脚本 我正在尝试在单击表单的提交按钮时在弹出窗口中加载 PHP 页面 弹出窗口对于如下按钮工作正常 来自 select php 的文本显示在弹出
  • 通过 Xcode 克隆特定的 git 分支

    我在从 Apple Xcode 克隆特定 git 分支时遇到困难 在 Xcode gt 源代码管理 gt 克隆并插入我的 HTTP 克隆 url 中 我只能克隆主分支 但我没有找到从 Xcode 克隆另一个开发人员分支的解决方案 通过使用终
  • 我可以读取文件并在编译时构造异构对象吗?

    情况 YAML 文件包含按名称排列的异构对象列表 如下所示 object Foo name Joe Bloggs age 26 object Bar location UK 对象不继承任何基类 也不共享彼此之间的任何类型的关系 除了它们看起