C ++ 17使用std :: variant表示DOM

编程入门 行业动态 更新时间:2024-10-19 14:30:15
本文介绍了C ++ 17使用std :: variant表示DOM的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

我正在尝试从C ++ 17学习如何使用std::variant.作为示例,开始使用它来表示DOM.尽管这项工作仍在进行中:

I'm trying to learn how to usestd::variant from C++17. As an example started using it, to represent the DOM. Though this is still work in progress:

  • 我想就std::variant
  • 的使用获得专家意见
  • 还有一些有关编译器支持的输入.
  • I wanted to get expert opinion on the usage of std::variant
  • also some inputs on the compiler support.
  • 我有DOM representation code( Godbolt的Compiler Explorer链接),它似乎可以很好地与 Clang trunk .但是,我看到同一代码无法使用 GCC 8.0.0 20171009 编译.

    I've the DOM representation code (Godbolt's Compiler Explorer link) and it seems to compile fine with Clang trunk. However, I see that the same code does not compile with GCC 8.0.0 20171009.

    我想了解这种不兼容的原因是什么.以及是否有人可以评论样式",以及这是否是std::variant的适当用法.

    I would like to understand what is the reason for this incompatibility. And also if anyone can comment on the "style" and if this is an appropriate usage of std::variant.

    #include <vector> #include <type_traits> #include <string> #include <variant> #include <unordered_map> // dom.spec.whatwg/ : reference for the DOM. namespace dragon { namespace dom { namespace traits_ns { template <bool valid_node_type = false> struct valid_node { static constexpr bool value = valid_node_type; }; template <typename T> struct is_valid_node { static constexpr bool value = std::is_base_of<valid_node<true>, T>::value && T::value; }; // TODO: Need to define policy concepts which will check if the children // of each node is of the right, allowed type. } struct Element; struct Text; struct Document; struct Document_type; struct Document_fragment; struct Processing_instruction; struct Comment; using AttrList = std::vector<std::pair<std::string, std::string>>; using AttrSet = std::unordered_map<std::string, std::string>; using Node = std::variant<Document, Document_type, Document_fragment, Element, Text, Processing_instruction, Comment>; using Children = std::vector<Node>; struct Element final : traits_ns::valid_node<true> { Element(std::string t, const Children& c, const AttrList& a) : tag{ t }, child{ c } {} Element() = default; ~Element() = default; std::string tag; Children child; AttrSet attr; }; struct Text final : traits_ns::valid_node<true> { explicit Text(std::string d) : data{ d } {} std::string data; }; struct Document final : traits_ns::valid_node<true> { Document() = default; ~Document() = default; }; struct Document_type final : traits_ns::valid_node<true> {}; struct Document_fragment final : traits_ns::valid_node<true> {}; struct Processing_instruction final : traits_ns::valid_node<true> {}; struct Comment final : traits_ns::valid_node<true> {}; } // namespace dom } // namespace dragon namespace dom = dragon::dom; using std::vector; int main() { dom::Node t{dom::Text{"Hello"}}; dom::Node e{dom::Element{"element", {}, {{"class", "blah"}}}}; return 0; }

    GCC产生的错误摘要:

    Snippet of errors Produced by GCC:

    #1 with x86-64 gcc (trunk) In file included from /opt/compiler-explorer/gcc-trunk-20171009/include/c++/8.0.0/bits/move.h:55:0, from /opt/compiler-explorer/gcc-trunk-20171009/include/c++/8.0.0/bits/stl_pair.h:59, from /opt/compiler-explorer/gcc-trunk-20171009/include/c++/8.0.0/bits/stl_algobase.h:64, from /opt/compiler-explorer/gcc-trunk-20171009/include/c++/8.0.0/vector:60, from <source>:1: /opt/compiler-explorer/gcc-trunk-20171009/include/c++/8.0.0/type_traits: In instantiation of 'struct std::is_trivially_destructible<dragon::dom::Document>': /opt/compiler-explorer/gcc-trunk-20171009/include/c++/8.0.0/type_traits:2859:25: required from 'constexpr const bool std::is_trivially_destructible_v<dragon::dom::Document>' /opt/compiler-explorer/gcc-trunk-20171009/include/c++/8.0.0/variant:309:5: required from 'constexpr const bool std::__detail::__variant::_Traits<dragon::dom::Document, dragon::dom::Document_type, dragon::dom::Document_fragment, dragon::dom::Element, dragon::dom::Text, dragon::dom::Processing_instruction, dragon::dom::Comment>::_S_trivial_dtor' /opt/compiler-explorer/gcc-trunk-20171009/include/c++/8.0.0/variant:317:20: required from 'constexpr const bool std::__detail::__variant::_Traits<dragon::dom::Document, dragon::dom::Document_type, dragon::dom::Document_fragment, dragon::dom::Element, dragon::dom::Text, dragon::dom::Processing_instruction, dragon::dom::Comment>::_S_trivial_move_assign' /opt/compiler-explorer/gcc-trunk-20171009/include/c++/8.0.0/variant:642:16: required by substitution of 'template<class ... _Types> using _Move_assign_alias = std::__detail::__variant::_Move_assign_base<std::__detail::__variant::_Traits<_Types>::_S_trivial_move_assign, _Types ...> [with _Types = {dragon::dom::Document, dragon::dom::Document_type, dragon::dom::Document_fragment, dragon::dom::Element, dragon::dom::Text, dragon::dom::Processing_instruction, dragon::dom::Comment}]' /opt/compiler-explorer/gcc-trunk-20171009/include/c++/8.0.0/variant:645:12: required from 'struct std::__detail::__variant::_Variant_base<dragon::dom::Document, dragon::dom::Document_type, dragon::dom::Document_fragment, dragon::dom::Element, dragon::dom::Text, dragon::dom::Processing_instruction, dragon::dom::Comment>' /opt/compiler-explorer/gcc-trunk-20171009/include/c++/8.0.0/variant:1032:11: required from 'class std::variant<dragon::dom::Document, dragon::dom::Document_type, dragon::dom::Document_fragment, dragon::dom::Element, dragon::dom::Text, dragon::dom::Processing_instruction, dragon::dom::Comment>' 41 : <source>:41:86: required from here /opt/compiler-explorer/gcc-trunk-20171009/include/c++/8.0.0/type_traits:1285:12: error: invalid use of incomplete type 'struct dragon::dom::Document' struct is_trivially_destructible ^~~~~~~~~~~~~~~~~~~~~~~~~ 28 : <source>:28:10: note: forward declaration of 'struct dragon::dom::Document' struct Document; ^~~~~~~~ In file included from /opt/compiler-explorer/gcc-trunk-20171009/include/c++/8.0.0/bits/move.h:55:0, from /opt/compiler-explorer/gcc-trunk-20171009/include/c++/8.0.0/bits/stl_pair.h:59, from /opt/compiler-explorer/gcc-trunk-20171009/include/c++/8.0.0/bits/stl_algobase.h:64, from /opt/compiler-explorer/gcc-trunk-20171009/include/c++/8.0.0/vector:60, from <source>:1: /opt/compiler-explorer/gcc-trunk-20171009/include/c++/8.0.0/type_traits: In instantiation of 'constexpr const bool std::is_trivially_destructible_v<dragon::dom::Document>': /opt/compiler-explorer/gcc-trunk-20171009/include/c++/8.0.0/variant:309:5: required from 'constexpr const bool std::__detail::__variant::_Traits<dragon::dom::Document, dragon::dom::Document_type, dragon::dom::Document_fragment, dragon::dom::Element, dragon::dom::Text, dragon::dom::Processing_instruction, dragon::dom::Comment>::_S_trivial_dtor' /opt/compiler-explorer/gcc-trunk-20171009/include/c++/8.0.0/variant:317:20: required from 'constexpr const bool std::__detail::__variant::_Traits<dragon::dom::Document, dragon::dom::Document_type, dragon::dom::Document_fragment, dragon::dom::Element, dragon::dom::Text, dragon::dom::Processing_instruction, dragon::dom::Comment>::_S_trivial_move_assign' <SNIP> dragon::dom::Document_fragment, dragon::dom::Element, dragon::dom::Text, dragon::dom::Processing_instruction, dragon::dom::Comment}]' is implicitly deleted because the default definition would be ill-formed: variant(const variant& __rhs) = default; ^~~~~~~ /opt/compiler-explorer/gcc-trunk-20171009/include/c++/8.0.0/variant:1087:7: error: use of deleted function 'constexpr std::_Enable_copy_move<false, false, false, false, _Tag>::_Enable_copy_move(const std::_Enable_copy_move<false, false, false, false, _Tag>&) [with _Tag = std::variant<dragon::dom::Document, dragon::dom::Document_type, dragon::dom::Document_fragment, dragon::dom::Element, dragon::dom::Text, dragon::dom::Processing_instruction, dragon::dom::Comment>]' In file included from /opt/compiler-explorer/gcc-trunk-20171009/include/c++/8.0.0/variant:38:0, from <source>:4: /opt/compiler-explorer/gcc-trunk-20171009/include/c++/8.0.0/bits/enable_special_members.h:301:15: note: declared here constexpr _Enable_copy_move(_Enable_copy_move const&) noexcept = delete; ^~~~~~~~~~~~~~~~~ Compiler exited with result code 1 x86-64 gcc (trunk) (Editor #1, Compiler #1) g++ (GCC-Explorer-Build) 8.0.0 20171009 (experimental)- cached

    推荐答案

    元素的构造函数取决于Node类型,而Node类型取决于其他节点类型.

    Element's constructor depends on the type Node, which depends on the other node types.

    就构造函数的定义而言,这些其他节点类型不是完整的类型(它们在下面定义).

    At the point of the definition of the constructor, these other node types are not complete types (they are defined below).

    将构造函数的主体移到节点类型定义下方:

    move the body of the constructor below the node type definitions:

    #include <vector> #include <type_traits> #include <string> #include <variant> #include <unordered_map> // dom.spec.whatwg/ : reference for the DOM. namespace dragon { namespace dom { namespace traits_ns { template <bool valid_node_type = false> struct valid_node { static constexpr bool value = valid_node_type; }; template <typename T> struct is_valid_node { static constexpr bool value = std::is_base_of<valid_node<true>, T>::value && T::value; }; // TODO: Need to define policy concepts which will check if the children // of each node is of the right, allowed type. } struct Element; struct Text; struct Document; struct Document_type; struct Document_fragment; struct Processing_instruction; struct Comment; using AttrList = std::vector<std::pair<std::string, std::string>>; using AttrSet = std::unordered_map<std::string, std::string>; using Node = std::variant<Document, Document_type, Document_fragment, Element, Text, Processing_instruction, Comment>; using Children = std::vector<Node>; struct Element final : traits_ns::valid_node<true> { Element(std::string t, const Children& c, const AttrList& a); Element() = default; ~Element() = default; std::string tag; Children child; AttrSet attr; }; struct Text final : traits_ns::valid_node<true> { explicit Text(std::string d) : data{ d } {} std::string data; }; struct Document final : traits_ns::valid_node<true> { Document() = default; ~Document() = default; }; struct Document_type final : traits_ns::valid_node<true> {}; struct Document_fragment final : traits_ns::valid_node<true> {}; struct Processing_instruction final : traits_ns::valid_node<true> {}; struct Comment final : traits_ns::valid_node<true> {}; Element::Element(std::string t, const Children& c, const AttrList& a) : tag{ t }, child{ c } {} } // namespace dom } // namespace dragon namespace dom = dragon::dom; using std::vector; int main() { dom::Node t{dom::Text{"Hello"}}; dom::Node e{dom::Element{"element", {}, {{"class", "blah"}}}}; return 0; }

    更多推荐

    C ++ 17使用std :: variant表示DOM

    本文发布于:2023-11-29 20:27:17,感谢您对本站的认可!
    本文链接:https://www.elefans.com/category/jswz/34/1647538.html
    版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
    本文标签:std   DOM   variant

    发布评论

    评论列表 (有 0 条评论)
    草根站长

    >www.elefans.com

    编程频道|电子爱好者 - 技术资讯及电子产品介绍!