c++ - Boost Karma,重新排序结构元素

标签 c++ boost boost-spirit

假设我有一个这样的结构:

struct MyStruct
{
    int a;
    int b; 
    int c;
}

BOOST_FUSION_ADAPT_STRUCT
(
    MyStruct,
    (int, a)
    (int, b)
    (int, c)
)

然后如果我有一个简单的生成器:

struct MyStructGenerator
    : boost::spirit::karma::grammar<boost::spirit::ostream_iterator, MyStruct()>
{
    MyStructGenerator() : MyStructGenerator::base_type(start_)
    {

        namespace bsk = boost::spirit::karma;

        start_ = '<' 
            << bsk::int_
            << ','
            << bsk::int_
            << ','
            << bsk::int_
            << '>';
    }

    ~MyStructGenerator() = default;
    boost::spirit::karma::rule<boost::spirit::ostream_iterator, MyStruct()> start_;
};

然后我运行以下命令:

int main()
{
    MyStruct ms = { 3, 2, 1 };
    std::cout << boost::spirit::karma::format(MyStructGenerator(), ms) << std::endl;
}

我当然希望看到 <3, 2, 1> .我想不通的是如何更改规则内的顺序?如果我想看 <1, 2, 3> 怎么办?或者即使我想看 <2, 1, 3>

此外,如果没有 BOOST_FUSION_ADAPT_STRUCT,我是否可以做到这一点? ?

最佳答案

Q1 如果我想看到 <1, 2, 3> 或者即使我想看到 <2, 1, 3> 怎么办?

只需更改适应的顺序:

简化 Live On Wandbox :

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

struct MyStruct { int a, b, c; };
BOOST_FUSION_ADAPT_STRUCT(MyStruct, a, b, c)

#include <boost/spirit/include/karma.hpp>
namespace bsk = boost::spirit::karma;

template <typename It = boost::spirit::ostream_iterator>
struct MyGen : bsk::grammar<It, MyStruct()> {
    MyGen() : MyGen::base_type(start_) {
        using namespace bsk;
        start_ = '<' << int_ << ',' << int_ << ',' << int_ << '>';
    }
  private:
    bsk::rule<It, MyStruct()> start_;
};

int main() {
    MyGen<> gen;
    std::cout << format(gen, MyStruct { 3, 2, 1 }) << "\n";
}

打印 <3,2,1> , 但是用

BOOST_FUSION_ADAPT_STRUCT(MyStruct, c, b, a)

打印 <1,2,3> .

Q2 不适应?

嗯。我可以向您展示一些您可能感兴趣的内容:

  1. 没有业力: Live On Wandbox :

    #include <boost/fusion/adapted/struct.hpp>
    
    struct MyStruct { int a, b, c; };
    BOOST_FUSION_ADAPT_STRUCT(MyStruct, c, b, a)
    
    #include <iostream>
    #include <boost/fusion/include/io.hpp>
    #include <boost/fusion/include/as_vector.hpp>
    using boost::fusion::as_vector;
    
    int main() {
        MyStruct ms { 3, 2, 1 };
        std::cout << as_vector(ms) << "\n";
    
        std::cout 
            << boost::fusion::tuple_open("<")
            << boost::fusion::tuple_delimiter(",")
            << boost::fusion::tuple_close(">");
    
        std::cout << as_vector(ms) << "\n";
    }
    

    打印

    (1 2 3)
    <1,2,3>
    
  2. 命名改编:您可以同时使用*_NAMED改编不同的顺序。宏。这是一个演示,展示了它同时使用 Fusion IO 和 Karma 生成器。

    Note I slightly modified the struct so it's easier to track which field is 'a', 'b' or 'c'.

    查看 Live On Wandbox :

    #include <boost/fusion/adapted/struct.hpp>
    
    struct MyStruct { char a, b, c; };
    BOOST_FUSION_ADAPT_STRUCT_NAMED(MyStruct, AsABC, a, b, c)
    BOOST_FUSION_ADAPT_STRUCT_NAMED(MyStruct, AsBCA, b, c, a)
    BOOST_FUSION_ADAPT_STRUCT_NAMED(MyStruct, AsCBA, c, b, a)
    
    #include <boost/spirit/include/karma.hpp>
    #include <boost/spirit/include/qi.hpp>
    namespace bsk = boost::spirit::karma;
    
    template <typename Attr, typename It = boost::spirit::ostream_iterator>
    struct MyGen : bsk::grammar<It, Attr()> {
        MyGen() : MyGen::base_type(start_) {
            using namespace bsk;
            start_ = '<' << auto_ << ',' << auto_ << ',' << auto_ << '>';
        }
      private:
        bsk::rule<It, Attr()> start_;
    };
    
    #include <iostream>
    #include <boost/fusion/include/io.hpp>
    #include <boost/fusion/include/as_vector.hpp>
    using boost::fusion::as_vector;
    
    template <typename Attr>
    void do_tests(Attr const& ms) {
        std::cout << as_vector(ms) << "\n";
        std::cout << format(MyGen<Attr>{}, ms) << "\n";
    }
    
    int main() {
        std::cout << boost::fusion::tuple_open("<") << boost::fusion::tuple_delimiter(",") << boost::fusion::tuple_close(">");
    
        MyStruct ms { 'a', 'b', 'c' };
    
        using namespace boost::fusion::adapted;
        do_tests(AsABC{ms});
        do_tests(AsCBA{ms});
        do_tests(AsBCA{ms});
    }
    

    打印

    <a,b,c>
    <a,b,c>
    <c,b,a>
    <c,b,a>
    <b,c,a>
    <b,c,a>
    
  3. 是的,你可以不适应(尽管不要):

    Live On Wandbox (由于编译时的限制,注释部分)

    struct MyStruct { char a, b, c; };
    
    #include <boost/spirit/include/karma.hpp>
    #include <boost/spirit/include/phoenix.hpp>
    namespace bsk = boost::spirit::karma;
    namespace phx = boost::phoenix;
    
    template <typename It = boost::spirit::ostream_iterator>
    struct MyGen : bsk::grammar<It, MyStruct()> {
        MyGen() : MyGen::base_type(start_) {
            using boost::proto::deep_copy;
            using namespace bsk;
            auto A = deep_copy(char_[ _1 = phx::bind(&MyStruct::a, _val) ]);
            auto B = deep_copy(char_[ _1 = phx::bind(&MyStruct::b, _val) ]);
            auto C = deep_copy(char_[ _1 = phx::bind(&MyStruct::c, _val) ]);
            start_ =
                '<' << A << ',' << B << ',' << C << '>' << eol <<
                '<' << A << ',' << C << ',' << B << '>' << eol <<
                '<' << B << ',' << A << ',' << C << '>' << eol <<
                '<' << C << ',' << A << ',' << B << '>' << eol <<
                '<' << B << ',' << C << ',' << A << '>' << eol <<
                '<' << C << ',' << B << ',' << A << '>' << eol
                ;
        }
      private:
        bsk::rule<It, MyStruct()> start_;
    };
    
    int main() {
        std::cout << format(MyGen<>{}, MyStruct { 'a', 'b', 'c' });
    }
    

    打印

    <a,b,c>
    <a,c,b>
    <b,a,c>
    <c,a,b>
    <b,c,a>
    <c,b,a>
    

关于c++ - Boost Karma,重新排序结构元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48646081/

相关文章:

c++ - 异常处理器

c++ - 或无效 C++ : why does this code compile?

c++ - 笔记本电脑触控板 WM_INPUT 上的 RAWINPUTHEADER hDevice null

c++ - Boost asio 绑定(bind)读取处理程序

c++ - 针对 Boost 库编译 Nuke 插件

C++ 为 T 的派生类覆盖 hash<T>

c++ - Boost 1_52 构建 VS2012 失败

c++ - 结合 boost::spirit 和 boost::any_range?

c++ - boost 灵气 : Compile error on slight rule change

boost 灵气 : Is it suitable language/tool to analyse/cut a "multiline" data file?