使用BOOST_FUSION_ADAPT_ADT修改类时出错 [英] Error when adapting a class with BOOST_FUSION_ADAPT_ADT

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

问题描述

我有以下课程:

  #ifndef WFRACTAL_FRACTAL_METADATA_H_ 
#define WFRACTAL_FRACTAL_METADATA_H_

#include< string>

命名空间WFractal {
命名空间分形{

类元数据{

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;
};

} //命名空间分形
} //命名空间WFractal

#endif //!WFRACTAL_FRACTAL_METADATA_H_

我想使用 boost :: spirit 从以下文件内容解析:

 元数据{
author =Me;
email =myemail;
brief =简要描述;
description =complete description;
}

我读过此页,我可以使用 BOOST_FUSION_ADAPT_STRUCT 以解析它。这是我的语法模板:

  #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>
#includeFractal / 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;
使用boost :: spirit :: ascii :: char_;
using boost :: spirit :: ascii :: no_case;

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

start%=
no_case [lit(metadata)]
>>'{'
> lit(author)]>>"'='>> quoted_string>>';'
>> no_case [lit(email)]> >" quoted_string>>"';'
>> no_case [lit(brief)]>"'='>> quoted_string> $ b>> 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
} //命名空间分形
} //命名空间WFractal

#endif //!WFRACTAL_FRACTAL_PARSER_METADATAGRAMMAR_H_

当我创建这个语法的实例时(总是在页面示例之后),我获得编译器错误:

  typedef string :: const_iterator StringIterator; 
typedef Parser :: MetadataParser< StringIterator>元数据解析器
MetadataParser parser;

我获得了很多错误许多此错误的副本:

  src / Fractal / FileFactory.cpp:27:17: usr / include / boost / spirit / home / qi / detail / assign_to.hpp:152:18:error:没有匹配函数调用'boost :: fusion :: extension :: adt_attribute_proxy< WFractal :: Fractal :: Metadata, 0,false> :: adt_attribute_proxy(const std :: __ cxx11 :: basic_string< char>&)'
attr = static_cast< Attribute>

我做错了什么?如何解决?



编辑



我添加了 #include< boost / spirit / include / support_adapt_adt_attributes.hpp> 标头,但这不工作。

  #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>
#includeFractal / Metadata.h

BOOST_FUSION_ADAPT_ADT(
WFractal :: Fractal ::元数据,
(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> b $ b ^(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;
};

}
} //命名空间分形
} //命名空间WFractal

#endif //!WFRACTAL_FRACTAL_PARSER_METADATAPARSER_H_


解决方案



与Modular Boost和git我发现这是一个回归。



这个拉回请求已部分修复了回归:





很遗憾,在置换解析器存在的情况下,它仍然被破坏。我已经测试了 BOOST_FUSION_ADAPT_STRUCT ,以验证它没有以其他方式打破。



将缩减的样本发送到PR以进行评论。同时,这里是自包含的复制器:



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 ::精神

boost :: spirit :: istream_iterator f(std :: cin),l; // input such 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)<< \\\
;
else
std :: cerr<< 解析失败\\\
;
}

如果你改变了 #if 1 #if 0 ,您将获得输出:

  Parsed:(ab)



/ strong>当然,假设你使用一个已应用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天全站免登陆