C++ Boost.Spirit与Boost.Variant和C++;11:应为零参数构造函数

C++ Boost.Spirit与Boost.Variant和C++;11:应为零参数构造函数,c++,boost,c++11,boost-spirit,boost-variant,C++,Boost,C++11,Boost Spirit,Boost Variant,我正在尝试使用Boost.Spirit编译一个简单的语法。我正在Arch Linux x86_64上使用g++4.7.0和boost 1.49.0-1.1 这里的最终目标是一个汇编程序。将有多个操作数,每个操作数具有一个类。所有操作数类型一起存储在boost::variant类型中 我成功地将此示例编译为direct规则,而它也是语法的基本类型,但引入操作数规则(并使其成为基本类型)会导致g++4.7.0抱怨: example.cpp:61:7: required from ‘Grammar

我正在尝试使用Boost.Spirit编译一个简单的语法。我正在Arch Linux x86_64上使用g++4.7.0和boost 1.49.0-1.1

这里的最终目标是一个汇编程序。将有多个操作数,每个操作数具有一个类。所有操作数类型一起存储在
boost::variant
类型中

我成功地将此示例编译为
direct
规则,而它也是语法的基本类型,但引入
操作数
规则(并使其成为基本类型)会导致g++4.7.0抱怨:

example.cpp:61:7:   required from ‘Grammar<Iterator>::Grammar() [with Iterator = __gnu_cxx::__normal_iterator<char*, std::basic_string<char> >]’
example.cpp:76:21:   required from here
/usr/include/boost/spirit/home/qi/detail/attributes.hpp:23:63: error: no matching function for call to ‘DirectOperand::DirectOperand()’
/usr/include/boost/spirit/home/qi/detail/attributes.hpp:23:63: note: candidates are:
example.cpp:20:12: note: DirectOperand::DirectOperand(const DirectValue&)
example.cpp:20:12: note:   candidate expects 1 argument, 0 provided
example.cpp:16:7: note: DirectOperand::DirectOperand(const DirectOperand&)
example.cpp:16:7: note:   candidate expects 1 argument, 0 provided
甚至编写一个helper函数来“强制”类型,如:

static Operand makeDirectOperand( const DirectOperand& op ) { return op; }

// ...

operand = directOp[&makeDirectOp];
但无论我做什么,它都会抱怨缺少默认构造函数

当我实际定义一个零参数构造函数时,我发现它已编译,但该
DirectOperand::value\uu
从未改变我指定的默认值

这是密码。它尽可能短

#include <cstdint>
#include <iostream>
#include <string>

#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/qi_uint.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/spirit/include/phoenix_fusion.hpp>
#include <boost/spirit/include/phoenix_stl.hpp>
#include <boost/variant.hpp>

typedef std::uint16_t DataWord;
typedef boost::variant<std::string, DataWord> DirectValue;

class DirectOperand {
private:
  DirectValue value_;
public:
  explicit DirectOperand( const DirectValue& value ) :
  value_( value ) {}

  const DirectValue& value() const { return value_; }
};

// For example purposes, but there will be multiple operand types
// here.
typedef boost::variant<DirectOperand> Operand;

namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;

template <typename Iterator>
struct Grammar : qi::grammar<Iterator, Operand(), ascii::space_type> {
   Grammar() : Grammar::base_type( operand ) {
      using qi::lexeme;
      using ascii::char_;
      using qi::uint_parser;
      using namespace qi::labels;

      uint_parser<DataWord, 16, 1, 4> uhex_p;
      uint_parser<DataWord, 10, 1, 5> uint_p;

      word =
        char_( "a-zA-Z._" ) [_val += _1]
        >> *char_( "a-zA-Z0-9._" ) [_val += _1]
        ;

      number = (
        "0x" >> uhex_p
        | uint_p
        )
        [_val = _1]
        ;

      direct %= ( word | number );

      directOp %= direct;

      // This would be ( directOp | indirectOp | etc)
      operand %= directOp;
   }

  qi::rule<Iterator, DataWord(), ascii::space_type> number;
  qi::rule<Iterator, std::string()> word;
  qi::rule<Iterator, DirectValue(), ascii::space_type> direct;
  qi::rule<Iterator, DirectOperand(), ascii::space_type> directOp;
  qi::rule<Iterator, Operand(), ascii::space_type> operand;
};

int main() {
   std::string line;

   typedef std::string::iterator iterator_type;
   typedef Grammar<iterator_type> Grammar;
   Grammar grammar {};
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
typedef std::uint16_t数据字;
typedef boost::variant DirectValue;
类直接操作数{
私人:
直接值;
公众:
显式DirectOperator(常量DirectValue和值):
值{(值){}
常量DirectValue&value()常量{返回值}
};
//例如,但将有多种操作数类型
//在这里。
typedef boost::变量操作数;
名称空间qi=boost::spirit::qi;
名称空间ascii=boost::spirit::ascii;
模板
结构语法:qi::Grammar{
语法():语法::基类型(操作数){
使用气:词素;
使用ascii::char;
使用qi::uint\u解析器;
使用名称空间qi::标签;
uint_解析器uhex_p;
uint_解析器uint_p;
话=
字符(“a-zA-Z.”[u val+=\u 1]
>>*字符(a-zA-Z0-9.)
;
数字=(
“0x”>>uhex\u p
|尤努普
)
[[u val=[u 1]
;
直接%=(字数);
directOp%=直接;
//这将是(directOp | indirectOp |等)
操作数%=directOp;
}
qi:规则编号;
齐:规则词;
气:规则直接;
qi::rule directOp;
qi::规则操作数;
};
int main(){
std::字符串行;
typedef std::string::iterator iterator_type;
类型定义语法;
语法{};
}

我认为属性
qi::rule
directOp
此处)的实例化需要默认构造函数


如果您不愿意在
DirectOperand
中包含默认构造函数,可以尝试将其包装在
boost::optional
中,以推迟初始化。

是的,这就是问题所在。Boost.Optional很好地解决了这个问题。当调用默认构造函数时,我在问题中关于垃圾的评论实际上是由于缺少调试符号。“可选”在某些情况下似乎不适用于x3。你能解释一下什么是Qi中的解引用选项吗?@IgorR:对不起,我已经有好几年没有和Qi合作了。。。现在快5年了,所以我不知道:(@sehe也许你可以安排一些光线?@IgorR。这是
移动到
,以及
boost::spirit::x3
中的其他特征。如果你有一个“它不起作用”的具体案例,我可能能够解释它或确认一个bug
#include <cstdint>
#include <iostream>
#include <string>

#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/qi_uint.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/spirit/include/phoenix_fusion.hpp>
#include <boost/spirit/include/phoenix_stl.hpp>
#include <boost/variant.hpp>

typedef std::uint16_t DataWord;
typedef boost::variant<std::string, DataWord> DirectValue;

class DirectOperand {
private:
  DirectValue value_;
public:
  explicit DirectOperand( const DirectValue& value ) :
  value_( value ) {}

  const DirectValue& value() const { return value_; }
};

// For example purposes, but there will be multiple operand types
// here.
typedef boost::variant<DirectOperand> Operand;

namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;

template <typename Iterator>
struct Grammar : qi::grammar<Iterator, Operand(), ascii::space_type> {
   Grammar() : Grammar::base_type( operand ) {
      using qi::lexeme;
      using ascii::char_;
      using qi::uint_parser;
      using namespace qi::labels;

      uint_parser<DataWord, 16, 1, 4> uhex_p;
      uint_parser<DataWord, 10, 1, 5> uint_p;

      word =
        char_( "a-zA-Z._" ) [_val += _1]
        >> *char_( "a-zA-Z0-9._" ) [_val += _1]
        ;

      number = (
        "0x" >> uhex_p
        | uint_p
        )
        [_val = _1]
        ;

      direct %= ( word | number );

      directOp %= direct;

      // This would be ( directOp | indirectOp | etc)
      operand %= directOp;
   }

  qi::rule<Iterator, DataWord(), ascii::space_type> number;
  qi::rule<Iterator, std::string()> word;
  qi::rule<Iterator, DirectValue(), ascii::space_type> direct;
  qi::rule<Iterator, DirectOperand(), ascii::space_type> directOp;
  qi::rule<Iterator, Operand(), ascii::space_type> operand;
};

int main() {
   std::string line;

   typedef std::string::iterator iterator_type;
   typedef Grammar<iterator_type> Grammar;
   Grammar grammar {};
}