错误适应与BOOST_FUSION_ADAPT_ADT类时 [英] Error when adapting a class with BOOST_FUSION_ADAPT_ADT

查看:171
本文介绍了错误适应与BOOST_FUSION_ADAPT_ADT类时的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下类:

 的#ifndef WFRACTAL_FRACTAL_METADATA_H_
#定义WFRACTAL_FRACTAL_METADATA_H_#包括LT&;串GT;命名空间WFractal {
命名空间的分形{类的元数据{上市:    无效setAuthorName(常量标准::字符串&安培;名);
    无效setAuthorEMail(常量标准::字符串&安培;电子邮件);
    无效setBriefDescription(常量标准::字符串&安培;简介);
    无效setCompleteDescription(常量标准::字符串&安培;说明);
    标准::字符串getAuthorName()const的;
    标准::字符串getAuthorEMail()const的;
    标准::字符串getBriefDescription()const的;
    标准::字符串getCompleteDescription()const的;上市:    布尔运算符==(const的元数据和安培;其他);私人的:    标准::字符串m_name;
    标准::字符串m_email;
    标准::字符串m_brief;
    标准::字符串m_description;
};} //命名空间中的分形
} //命名空间WFractal#ENDIF //!WFRACTAL_FRACTAL_METADATA_H_

我想用解析它的boost ::精神从下列文件内容:

  {元
  笔者=我;
  电子邮件=myemail;
  简短=简要说明;
  说明=完整说明;
}

我从的我可以使用 BOOST_FUSION_ADAPT_STRUCT 为了解析这个页面。这是我的语法模板:

 的#ifndef WFRACTAL_FRACTAL_PARSER_METADATAGRAMMAR_H_
#定义WFRACTAL_FRACTAL_PARSER_METADATAGRAMMAR_H_#包括LT&;升压/融合/调整/ ADT / adapt_adt.hpp>
#包括LT&;升压/融合/有/ adapt_adt.hpp>
#包括LT&;升压/精神/有/ qi_no_case.hpp>
#包括LT&;串GT;
#包括分形/ Metadata.hBOOST_FUSION_ADAPT_ADT(
    WFractal ::分形::元数据,
    (obj.getAuthorName(),obj.setAuthorName(VAL))
    (obj.getAuthorEMail(),obj.setBriefDescription(VAL))
    (obj.getBriefDescription(),obj.setCompleteDescription(VAL))
    (obj.getCompleteDescription(),obj.setAuthorEMail(VAL))
)命名空间WFractal {
命名空间的分形{
命名空间解析器{模板< typename的迭代器>
结构MetadataParser:提振精神:: ::气::语法<迭代器,元数据()的boost ::精神:: ASCII ::空间类型> {
    MetadataParser():MetadataParser :: base_type(开始){
        使用boost ::精神::补气:: int_;
        使用boost ::精神::补气::点燃;
        使用boost ::精神::补气:: double_;
        使用boost ::精神::补气::词位;
        使用boost ::精神:: ASCII :: char_;
        使用boost ::精神:: ASCII :: NO_CASE;        quoted_string%=语义[''>> +(char_ - ')GT;> ''];        启动(%)=
        NO_CASE [亮起(元数据)
        >> {
        >> NO_CASE [亮起(作家)]>> '='>> quoted_string>> ';'
        >> NO_CASE [亮(电子邮件)>> '='>> quoted_string>> ';'
        >> NO_CASE [亮起(简报)>> '='>> quoted_string>> ';'
        >> NO_CASE [点亮(说明)]≥> '='>> quoted_string>> ';'
        >> }
        ;
    }    提振精神:: ::气::规则<迭代器,标准::字符串(),升压::精神:: ASCII ::空间类型> quoted_string;
    提振精神:: ::气::规则<迭代器,元数据()的boost ::精神:: ASCII ::空间类型>开始;
};} //命名空间分析器
} //命名空间中的分形
} //命名空间WFractal#ENDIF //!WFRACTAL_FRACTAL_PARSER_METADATAGRAMMAR_H_

当我创建这个语法的一个实例(总是沿着页面的例子),我得到编译器错误:

 的typedef字符串::为const_iterator StringIterator;
typedef的解析器:: MetadataParser< StringIterator> MetadataParser;
MetadataParser分析器;

我得到了很多错误(典型的提振...)和我注意到在他们里面这个错误的许多副本:

 的src /分形/ FileFactory.cpp:27:17:从这里需要
/usr/include/boost/spirit/home/qi/detail/assign_to.hpp:152:18:错误:调用'的boost ::融合::扩展:: adt_attribute_proxy&LT没有匹配功能; WFractal ::分形::元,0,假> :: adt_attribute_proxy(常量的std :: __ cxx11 :: basic_string的<焦炭>&安培;)
             ATTR =的static_cast<属性与GT;(VAL);

我在做什么错?我怎样才能解决这个问题?

修改

正如所建议的M.S.我已经添加了的#include<升压/精神/有/ support_adapt_adt_attributes.hpp方式> 头,但是这是行不通的。

 的#ifndef WFRACTAL_FRACTAL_PARSER_METADATAPARSER_H_
#定义WFRACTAL_FRACTAL_PARSER_METADATAPARSER_H_#包括LT&;升压/配置/ warning_disable.hpp>
#包括LT&;升压/精神/有/ qi.hpp>
#包括LT&;升压/精神/有/ phoenix_core.hpp>
#包括LT&;升压/精神/有/ phoenix_operator.hpp>
#包括LT&;升压/精神/有/ phoenix_object.hpp>
#包括LT&;升压/融合/有/ io.hpp>
#包括LT&;升压/融合/调整/ ADT / adapt_adt.hpp>
#包括LT&;升压/融合/有/ adapt_adt.hpp>
#包括LT&;升压/精神/有/ support_adapt_adt_attributes.hpp>
#包括LT&;串GT;
#包括分形/ Metadata.hBOOST_FUSION_ADAPT_ADT(
    WFractal ::分形::元数据,
    (obj.getAuthorName(),obj.setAuthorName(VAL))
    (obj.getAuthorEMail(),obj.setAuthorEMail(VAL))
    (obj.getBriefDescription(),obj.setBriefDescription(VAL))
    (obj.getCompleteDescription(),obj.setCompleteDescription(VAL))
)命名空间WFractal {
命名空间的分形{
命名空间解析器{模板< typename的迭代器>
结构MetadataParser:提振精神:: ::气::语法<迭代器,元数据()的boost ::精神:: ASCII ::空间类型> {
    MetadataParser():MetadataParser :: base_type(开始){
        使用boost ::精神::补气::点燃;
        使用boost ::精神::补气::词位;
        使用boost ::精神:: ASCII :: char_;
        使用boost ::精神:: ASCII :: NO_CASE;        quoted_string%=语义[''>> +(char_ - ')GT;> ''];        启动(%)=
        NO_CASE [亮起(元数据)
        >> {
        >> ((NO_CASE [亮起(作家)]>>'='>> quoted_string>>';')
        ^(NO_CASE [亮(电子邮件)>>'='>> quoted_string>>';')
        ^(NO_CASE [亮起(简报)>>'='>> quoted_string>>';')
        ^(NO_CASE [点亮(说明)]≥>'='>> quoted_string>>';'))
        >> }
        ;
    }    提振精神:: ::气::规则<迭代器,标准::字符串(),升压::精神:: ASCII ::空间类型> quoted_string;
    提振精神:: ::气::规则<迭代器,元数据()的boost ::精神:: ASCII ::空间类型>开始;
};} //命名空间分析器
} //命名空间中的分形
} //命名空间WFractal#ENDIF //!WFRACTAL_FRACTAL_PARSER_METADATAPARSER_H_


解决方案

嗯。

与模块化升压和Git很长时间的斗争后...我发现这是一个倒退。

回归了这个pull请求得到部分修正:

不幸的是,它仍然打破了置换分析器的presence。我和 BOOST_FUSION_ADAPT_STRUCT 测试,以验证它是不以其他方式打破。

我会减少样品添加到PR征求意见。同时,这里是做整装重现:

<大骨节病> 住在Coliru

 的#include&LT;升压/精神/有/ qi.hpp&GT;
#包括LT&;升压/融合/ adapted.hpp&GT;
#包括LT&;&iostream的GT;类Foo {
  上市:
    字符常量和放大器;木屐()const的{返回; }
    字符常量和放大器; getB()const的{回复B; }    无效SETA(char值){a =值; }
    无效组B(char值){B =价值; }
  私人的:
    烧焦A,B;
};BOOST_FUSION_ADAPT_ADT(
        美孚,
        (字符常量和放大器;,字符常量和放大器;,obj.getA(),obj.setA(VAL))
        (字符常量和放大器;,字符常量和放大器;,obj.getB(),obj.setB(VAL))
    )
诠释主(){
    命名空间补气=的boost ::精神::补气;    提振精神:: :: istream_iterator F(的std :: CIN),L; //输入例如A = A; B =;
    富富;    BOOL R =气::解析(F,L,
#如果0 //编译失败
                      (A =&GT;&GT;气虚:: char_&GT;&GT;';')
                    ^(B =&GT;&GT;气虚:: char_&GT;&GT;';')
#else伪//使用FIX汇集了来自PR#153
                      (A =&GT;&GT;气虚:: char_&GT;&GT;';')
                   &GT;&GT; (B =&GT;&GT;气虚:: char_&GT;&GT;';')
#万一
                ,富);    如果(r)的
        性病::法院LT&;&LT; 经分析:&LT;&LT;提高::融合:: as_vector(富)&LT;&LT; \\ n;
    其他
        的std :: CERR&LT;&LT; 解析失败\\ n;
}

如果你,但是,更改#如果1 0#如果,你得到的输出:

 解析的:(A B)


  

注意当然,这是假设你使用具有PR 153的应用。一个分支


I've the following class:

#ifndef WFRACTAL_FRACTAL_METADATA_H_
#define WFRACTAL_FRACTAL_METADATA_H_

#include <string>

namespace WFractal {
namespace Fractal {

class Metadata {

public:

    void setAuthorName(const std::string &name);
    void setAuthorEMail(const std::string &email);
    void setBriefDescription(const std::string &brief);
    void setCompleteDescription(const std::string &description);
    std::string getAuthorName() const;
    std::string getAuthorEMail() const;
    std::string getBriefDescription() const;
    std::string getCompleteDescription() const;

public:

    bool operator==(const Metadata &other);

private:

    std::string m_name;
    std::string m_email;
    std::string m_brief;
    std::string m_description;
};

} // namespace Fractal
} // namespace WFractal

#endif // !WFRACTAL_FRACTAL_METADATA_H_

I want to parse it using boost::spirit from following file content:

metadata {
  author = "Me";
  email = "myemail";
  brief = "brief description";
  description = "complete description";
}

I've read from this page that I can use BOOST_FUSION_ADAPT_STRUCT in order to parse it. This is my grammar template:

#ifndef WFRACTAL_FRACTAL_PARSER_METADATAGRAMMAR_H_
#define WFRACTAL_FRACTAL_PARSER_METADATAGRAMMAR_H_

#include <boost/fusion/adapted/adt/adapt_adt.hpp>
#include <boost/fusion/include/adapt_adt.hpp>
#include <boost/spirit/include/qi_no_case.hpp>
#include <string>
#include "Fractal/Metadata.h"

BOOST_FUSION_ADAPT_ADT(
    WFractal::Fractal::Metadata,
    (obj.getAuthorName(), obj.setAuthorName(val))
    (obj.getAuthorEMail(), obj.setBriefDescription(val))
    (obj.getBriefDescription(), obj.setCompleteDescription(val))
    (obj.getCompleteDescription(), obj.setAuthorEMail(val))
)

namespace WFractal {
namespace Fractal {
namespace Parser {

template <typename Iterator>
struct MetadataParser : boost::spirit::qi::grammar<Iterator, Metadata(), boost::spirit::ascii::space_type> {
    MetadataParser() : MetadataParser::base_type(start) {
        using boost::spirit::qi::int_;
        using boost::spirit::qi::lit;
        using boost::spirit::qi::double_;
        using boost::spirit::qi::lexeme;
        using boost::spirit::ascii::char_;
        using boost::spirit::ascii::no_case;

        quoted_string %= lexeme['"' >> +(char_ - '"') >> '"'];

        start %=
        no_case[lit("metadata")]
        >> '{'
        >>  no_case[lit("author")] >> '=' >> quoted_string >> ';'
        >>  no_case[lit("email")] >> '=' >> quoted_string >> ';'
        >>  no_case[lit("brief")] >> '=' >> quoted_string >> ';'
        >>  no_case[lit("description")] >> '=' >> quoted_string >> ';'
        >>  '}'
        ;
    }

    boost::spirit::qi::rule<Iterator, std::string(), boost::spirit::ascii::space_type> quoted_string;
    boost::spirit::qi::rule<Iterator, Metadata(), boost::spirit::ascii::space_type> start;
};

} // namespace Parser
} // namespace Fractal
} // namespace WFractal

#endif // !WFRACTAL_FRACTAL_PARSER_METADATAGRAMMAR_H_

When I create an instance of this grammar (always following the page example), I obtain compiler error:

typedef string::const_iterator StringIterator;
typedef Parser::MetadataParser<StringIterator> MetadataParser;
MetadataParser parser;

I obtain a lot of errors (typical of boost...) and I've noticed inside them many copy of this error:

src/Fractal/FileFactory.cpp:27:17:   required from here
/usr/include/boost/spirit/home/qi/detail/assign_to.hpp:152:18: error: no matching function for call to ‘boost::fusion::extension::adt_attribute_proxy<WFractal::Fractal::Metadata, 0, false>::adt_attribute_proxy(const std::__cxx11::basic_string<char>&)’
             attr = static_cast<Attribute>(val);

What I'm doing wrong? How can I fix it?

EDIT

As suggested by m.s. I've added the #include <boost/spirit/include/support_adapt_adt_attributes.hpp> header but this is not working.

#ifndef WFRACTAL_FRACTAL_PARSER_METADATAPARSER_H_
#define WFRACTAL_FRACTAL_PARSER_METADATAPARSER_H_

#include <boost/config/warning_disable.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/spirit/include/phoenix_object.hpp>
#include <boost/fusion/include/io.hpp>
#include <boost/fusion/adapted/adt/adapt_adt.hpp>
#include <boost/fusion/include/adapt_adt.hpp>
#include <boost/spirit/include/support_adapt_adt_attributes.hpp>
#include <string>
#include "Fractal/Metadata.h"

BOOST_FUSION_ADAPT_ADT(
    WFractal::Fractal::Metadata,
    (obj.getAuthorName(), obj.setAuthorName(val))
    (obj.getAuthorEMail(), obj.setAuthorEMail(val))
    (obj.getBriefDescription(), obj.setBriefDescription(val))
    (obj.getCompleteDescription(), obj.setCompleteDescription(val))
)

namespace WFractal {
namespace Fractal {
namespace Parser {

template <typename Iterator>
struct MetadataParser : boost::spirit::qi::grammar<Iterator, Metadata(), boost::spirit::ascii::space_type> {
    MetadataParser() : MetadataParser::base_type(start) {
        using boost::spirit::qi::lit;
        using boost::spirit::qi::lexeme;
        using boost::spirit::ascii::char_;
        using boost::spirit::ascii::no_case;

        quoted_string %= lexeme['"' >> +(char_ - '"') >> '"'];

        start %=
        no_case[lit("metadata")]
        >> '{'
        >> ((no_case[lit("author")] >> '=' >> quoted_string >> ';')
        ^  (no_case[lit("email")] >> '=' >> quoted_string >> ';')
        ^  (no_case[lit("brief")] >> '=' >> quoted_string >> ';')
        ^  (no_case[lit("description")] >> '=' >> quoted_string >> ';'))
        >>  '}'
        ;
    }

    boost::spirit::qi::rule<Iterator, std::string(), boost::spirit::ascii::space_type> quoted_string;
    boost::spirit::qi::rule<Iterator, Metadata(), boost::spirit::ascii::space_type> start;
};

} // namespace Parser
} // namespace Fractal
} // namespace WFractal

#endif // !WFRACTAL_FRACTAL_PARSER_METADATAPARSER_H_

解决方案

Hmm.

After very long struggle with Modular Boost and git... I've found that this is a regression.

The regression has been partially fixed by this pull request:

Sadly, it's still broken in the presence of the permutation parser. I've tested with BOOST_FUSION_ADAPT_STRUCT to verify that it is not broken in some other way.

I'll add the reduced sample to the PR for comments. Meanwhile, here's the reproducer made selfcontained:

Live On Coliru

#include <boost/spirit/include/qi.hpp>
#include <boost/fusion/adapted.hpp>
#include <iostream>

class Foo {
  public:
    char const& getA() const { return a; } 
    char const& getB() const { return b; } 

    void setA(char value)    { a = value; } 
    void setB(char value)    { b = value; } 
  private:
    char a, b;
};

BOOST_FUSION_ADAPT_ADT(
        Foo,
        (char const&, char const&, obj.getA(), obj.setA(val))
        (char const&, char const&, obj.getB(), obj.setB(val))
    )


int main() {
    namespace qi = boost::spirit::qi;

    boost::spirit::istream_iterator f(std::cin), l; // input e.g. "a=a;b=b;"
    Foo foo;

    bool r = qi::parse(f, l,
#if 0 // FAILS TO COMPILE
                      ("a=" >> qi::char_ >> ';')
                    ^ ("b=" >> qi::char_ >> ';')
#else // COMPILES WITH FIX FROM PR #153
                      ("a=" >> qi::char_ >> ';')
                   >> ("b=" >> qi::char_ >> ';')
#endif 
                , foo);

    if (r)
        std::cout << "Parsed: " << boost::fusion::as_vector(foo) << "\n";
    else
        std::cerr << "Parse failed\n";
}

If you, however, change the #if 1 to #if 0, you get the output:

Parsed: (a b)

Note of course that's assuming you use a branch that has the PR 153 applied.

这篇关于错误适应与BOOST_FUSION_ADAPT_ADT类时的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆