build error with boost spirit grammar (boost 1.43 and g++ 4.4.1) part III
Ok
i am trying to build a grammar and currently it looks like this:
#ifndef _INPUTGRAMMAR_H
#define _INPUTGRAMMAR_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_fusion.hpp>
#include <boost/spirit/include/phoenix_stl.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/variant/recursive_variant.hpp>
#include <boost/spirit/home/support/context.hpp>
#include <boost/spirit/home/phoenix.hpp>
#include <boost/foreach.hpp>
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
namespace sp = boost::spirit;
namespace qi = boost::spirit::qi;
using namespace boost::spirit::ascii;
namespace fusion = boost::fusion;
namespace phoenix = boost::phoenix;
using phoenix::at_c;
using phoenix::push_back;
using phoenix::bind;
template< typename Iterator , typename ExpressionAST >
struct InputGrammar : qi::grammar<Iterator, ExpressionAST(), space_type> {
InputGrammar() : InputGrammar::base_type( command ) {
identifier %= ( qi::char_("a-zA-Z_") >> *qi::char_("a-zA-Z_0-9") );
tag = identifier
[
at_c<0>(qi::_val) = qi::_1,
phoenix::bind( &ExpressionAST::setAsTag , qi::_val )
];
command =
identifier
[
at_c<0>(qi::_val) = qi::_1,
phoenix::bind( &ExpressionAST::setAsCommand , qi::_val )
]
>> "("
>> -(parameter % ",")
[
//phoenix::push_back(at_c<1>(qi::_val) , qi::_1 )
phoenix::bind( &std::vector< ExpressionAST , std::allocator< ExpressionAST > >::push_back, at_c<1>(qi::_val) , qi::_1 )
]
>> ")";
parameter = ( command | tag ) [qi::_val = qi::_1];
}
qi::rule< Iterator , ExpressionAST() , space_type > tag;
qi::rule< Iterator , std::string() , space_type > identifier;
qi::rule< Iterator , ExpressionAST() , space_type > command;
qi::rule< Iterator , ExpressionAST() , space_type > parameter;
};
#endif /* _INPUTGRAMMAR_H */
a snip of the build error is the following, basically it says that is trying to initialise a MockExpressionNode& (likely the push_back argument) with a std::vector< MockExpressionNode >, like somehow phoenix::bind where switching the order of the object and the parameter arguments.
../InputParser/InputGrammar.h:63: instantiated from ‘InputGrammar<Iterator, ExpressionAST>::InputGrammar() [with Iterator = __gnu_cxx::__normal_iterator<const char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, ExpressionAST = MockExpressionNode]’
tests_main.cpp:202: instantiated from here
/home/mineq/third_party/boost_1_43_0/boost/spirit/home/phoenix/bind/detail/member_function_ptr.hpp:103: error: invalid initialization of reference of type ‘const MockExpressionNode&’ from expression of type ‘std::vector<MockExpressionNode, std::allocator<MockExpressionNode> >’
/home/mineq/third_party/boost_1_43_0/boost/spirit/home/phoenix/bind/detail/member_function_ptr.hpp:103: error: return-statement with a value, in function returning 'void'
I tried the phoenix::bind to std::vector::push_back only after trying this original form:
>> -(parameter % ",")
[
phoenix::push_back(at_c<1>(qi::_val) , qi::_1 )
// phoenix::bind( &std::vector< ExpressionAST , std::allocator< ExpressionAST > >::push_back, at_c<1>(qi::_val) , qi::_1 )
]
>> ")";
i got this error instead (only final portion) about no matching function for std::vector::push_back:
boost::fusion::cons<boost::spirit::qi::literal_char<boost::spirit::char_encoding::standard, true, false>, boost::fusion::cons<boost::spirit::qi::optional<boost::spirit::qi::action<boost::spirit::qi::list<boost::spirit::qi::reference<const boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, MockExpressionNode(), boost::proto::exprns_::expr<boost::proto::tag::terminal, boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> >, 0l>, boost::fusion::unused_type, boost::fusion::unused_type> >, boost::spirit::qi::literal_char<boost::spirit::char_encoding::standard, true, false> >, boost::phoenix::actor<boost::phoenix::composite<boost::phoenix::detail::function_eval<2>, boost::fusion::vector<boost::phoenix::value<boost::phoenix::stl::push_back>, boost::phoenix::composite<boost::phoenix::at_eval<1>, boost::fusion::vector<boost::spirit::attribute<0>, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_> >, boost::spirit::argument<0>, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_> > > > >, boost::fusion::cons<boost::spirit::qi::literal_char<boost::spirit::char_encoding::standard, true, false>, boost::fusion::nil> > > > >, mpl_::bool_<false> >, R = bool, T0 = __gnu_cxx::__normal_iterator<const char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >&, T1 = const __gnu_cxx::__normal_iterator<const char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >&, T2 = boost::spirit::context<boost::fusion::cons<MockExpressionNode&, boost::fusion::nil>, boost::fusion::vector0<void> >&, T3 = const boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> >&]’
/home/mineq/third_party/boost_1_43_0/boost/spirit/home/qi/nonterminal/rule.hpp:201: instantiated from ‘boost::spirit::qi::rule<Iterator, T1, T2, T3, T4>& boost::spirit::qi::rule<Iterator, T1, T2, T3, T4>::operator=(const Expr&) [with Expr = boost::proto::exprns_::expr<boost::proto::tag::shift_right, boost::proto::argsns_::list2<const boost::proto::exprns_::expr<boost::proto::tag::shift_right, boost::proto::argsns_::list2<const boost::proto::exprns_::expr<boost::proto::tag::shift_right, boost::proto::argsns_::list2<const boost::proto::exprns_::expr<boost::proto::tag::subscript, boost::proto::argsns_::list2<boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::string(), boost::proto::exprns_::expr<boost::proto::tag::terminal, boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> >, 0l>, boost::fusion::unused_type, boost::fusion::unused_type>&, boost::proto::exprns_::expr<boost::proto::tag::terminal, boost::proto::argsns_::term<const boost::phoenix::actor<boost::phoenix::composite<boost::phoenix::sequence_eval, boost::fusion::vector<boost::phoenix::composite<boost::phoenix::assign_eval, boost::fusion::vector<boost::phoenix::composite<boost::phoenix::at_eval<0>, boost::fusion::vector<boost::spirit::attribute<0>, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_> >, boost::spirit::argument<0>, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::f开发者_运维百科usion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_> >, boost::phoenix::composite<boost::phoenix::detail::function_eval<1>, boost::fusion::vector<boost::phoenix::value<boost::phoenix::detail::member_function_ptr<0, void, void (MockExpressionNode::*)()> >, boost::spirit::attribute<0>, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_> >, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_> > >&>, 0l> >, 2l>&, boost::proto::exprns_::expr<boost::proto::tag::terminal, boost::proto::argsns_::term<const char (&)[2]>, 0l> >, 2l>&, const boost::proto::exprns_::expr<boost::proto::tag::negate, boost::proto::argsns_::list1<const boost::proto::exprns_::expr<boost::proto::tag::subscript, boost::proto::argsns_::list2<const boost::proto::exprns_::expr<boost::proto::tag::modulus, boost::proto::argsns_::list2<boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, MockExpressionNode(), boost::proto::exprns_::expr<boost::proto::tag::terminal, boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> >, 0l>, boost::fusion::unused_type, boost::fusion::unused_type>&, boost::proto::exprns_::expr<boost::proto::tag::terminal, boost::proto::argsns_::term<const char (&)[2]>, 0l> >, 2l>&, boost::proto::exprns_::expr<boost::proto::tag::terminal, boost::proto::argsns_::term<const boost::phoenix::actor<boost::phoenix::composite<boost::phoenix::detail::function_eval<2>, boost::fusion::vector<boost::phoenix::value<boost::phoenix::stl::push_back>, boost::phoenix::composite<boost::phoenix::at_eval<1>, boost::fusion::vector<boost::spirit::attribute<0>, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_> >, boost::spirit::argument<0>, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_> > >&>, 0l> >, 2l>&>, 1l>&>, 2l>&, boost::proto::exprns_::expr<boost::proto::tag::terminal, boost::proto::argsns_::term<const char (&)[2]>, 0l> >, 2l>, Iterator = __gnu_cxx::__normal_iterator<const char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, T1 = MockExpressionNode(), T2 = boost::proto::exprns_::expr<boost::proto::tag::terminal, boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> >, 0l>, T3 = boost::fusion::unused_type, T4 = boost::fusion::unused_type]’
../InputParser/InputGrammar.h:63: instantiated from ‘InputGrammar<Iterator, ExpressionAST>::InputGrammar() [with Iterator = __gnu_cxx::__normal_iterator<const char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, ExpressionAST = MockExpressionNode]’
tests_main.cpp:202: instantiated from here
/home/mineq/third_party/boost_1_43_0/boost/spirit/home/phoenix/stl/container/container.hpp:492: error: no matching function for call to ‘std::vector<MockExpressionNode, std::allocator<MockExpressionNode> >::push_back(const std::vector<MockExpressionNode, std::allocator<MockExpressionNode> >&)’
/usr/include/c++/4.4/bits/stl_vector.h:733: note: candidates are: void std::vector<_Tp, _Alloc>::push_back(const _Tp&) [with _Tp = MockExpressionNode, _Alloc = std::allocator<MockExpressionNode>]
/home/mineq/third_party/boost_1_43_0/boost/spirit/home/phoenix/stl/container/container.hpp:492: error: return-statement with a value, in function returning 'void'
The second form using phoenix::push_back is the suggested one. The problem is where the semantic action is defined. The -(whatever % ",")
construct has an attribute value type of vector<whatever>
, which you then pass as the parameter of push_back called on the vector<MockExpressionNode>
. In other words, spirit is not switching the arguments, the code is essentially vector<>.push_back(vector<>)
. You can see this in the third line of the last error block you posted:
/home/.../container.hpp:492: error: no matching function for call to ‘std::vector<...>::push_back(const std::vector<...>&)’
Debugging compile errors with this stuff sometimes requires reading between the lines, literally ;)
Instead, attach the push_back action to the parameter
parser directly, since this parser has the attribute type MockExpressionNode
. Try:
command =
identifier
[
at_c<0>(qi::_val) = qi::_1,
phoenix::bind( &ExpressionAST::setAsCommand , qi::_val )
]
>> "("
>> -(
parameter[ phoenix::push_back(at_c<1>(qi::_val) , qi::_1 ) ]
% ","
)
>> ")";
精彩评论