Question

I have a simple grammar written in Boost::Spirit defined as follows:

template <typename Iterator_T>
struct my_grammar :
qi::grammar<Iterator_T, vector<basic_value_t>(), qi::locals<size_t> >
{
  my_grammar();

  qi::rule<Iterator_T, vector<basic_value_t>(), qi::locals<size_t> > start;
  qi::rule<Iterator_T, basic_value_t(), qi::locals<size_t> > ptuple;
};

template <typename Iterator_T>
my_grammar<Iterator_T>::
my_grammar() : my_grammar<Iterator_T>::base_type(start), start(), ptuple() {
  start = (*ptuple);

  ptuple
    = (qi::byte_ >>
       qi::omit[qi::byte_[qi::_a = qi::_1]] >>
       qi::repeat(qi::_a)[qi::byte_])
    ;
}

basic_value_t defined as:

struct basic_value_t {
  uint8_t type;        
  vector<uint8_t> val;
};

is wrapped in BOOST_FUSION_ADAPT_STRUCT as:

BOOST_FUSION_ADAPT_STRUCT
(
 basic_value_t,
 (std::uint8_t, type)
 (std::vector<std::uint8_t>, val)
)

The grammar is then initialized with the following statement:

my_grammar<vector<uint8_t>::const_iterator> grammar;

It is on this line that I get an error when compiling the code with boost 1.54. However, if I compile the same code using boost 1.49 I do not get an error. As best I can figure, I have a subtle bug somewhere that is only showing itself when I move to the updated version of Boost.

The following is the error last portion of a very long error message sequence.

/home/making/Dev/filename.cpp:498:51: required from here
/usr/include/boost/fusion/view/transform_view/detail/value_of_impl.hpp:36:79: error: no type named ‘type’ in ‘struct boost::mpl::apply<boost::fusion::detail::apply_transform_result<boost::spirit::traits::build_attribute_sequence<boost::fusion::cons<boost::spirit::qi::any_binary_parser<boost::spirit::qi::detail::integer<8>, (boost::spirit::endian::endianness)2, 8>, boost::fusion::cons<boost::spirit::qi::omit_directive<boost::spirit::qi::action<boost::spirit::qi::any_binary_parser<boost::spirit::qi::detail::integer<8>, (boost::spirit::endian::endianness)2, 8>, boost::phoenix::actor<boost::phoenix::composite<boost::phoenix::assign_eval, boost::fusion::vector<boost::spirit::local_variable<0>, 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::void_> > > > >, boost::fusion::cons<boost::spirit::qi::lazy_directive<boost::phoenix::actor<boost::phoenix::composite<boost::phoenix::detail::function_eval<1>, boost::fusion::vector<boost::phoenix::value<boost::spirit::terminal<boost::spirit::tag::repeat> >, boost::spirit::local_variable<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::spirit::qi::any_binary_parser<boost::spirit::qi::detail::integer<8>, (boost::spirit::endian::endianness)2, 8>, boost::spirit::unused_type>, boost::fusion::nil> > >, boost::spirit::context<boost::fusion::cons<ccss_protocols::iec61850::basic_value_t&, boost::fusion::nil>, boost::fusion::vector1<long unsigned int> >, boost::spirit::traits::sequence_attribute_transform, __gnu_cxx::__normal_iterator<const unsigned char*, std::vector<unsigned char> >, boost::spirit::qi::domain>::element_attribute>, boost::spirit::qi::lazy_directive<boost::phoenix::actor<boost::phoenix::composite<boost::phoenix::detail::function_eval<1>, boost::fusion::vector<boost::phoenix::value<boost::spirit::terminal<boost::spirit::tag::repeat> >, boost::spirit::local_variable<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::spirit::qi::any_binary_parser<boost::spirit::qi::detail::integer<8>, (boost::spirit::endian::endianness)2, 8>, boost::spirit::unused_type>, mpl_::na, mpl_::na, mpl_::na, mpl_::na>’
             typedef typename mpl::apply<transform_type, value_type>::type type;
                                                                           ^
make[2]: *** [CMakeFiles/ccss-protocols-iec61850.dir/src/goose/application-layer.cpp.o] Error 1

Thank you in advance for your consideration of this error.

Was it helpful?

Solution

Defining

#define BOOST_SPIRIT_USE_PHOENIX_V3

fixes it as shown in the linked sample (thank @cv_and_he)

The reason why is documented in this existing answer:


Here's the fully working sample for future reference: Live on Coliru

#include <iostream>
#include <string>
#include <vector>

//#define BOOST_SPIRIT_USE_PHOENIX_V3

#include <boost/spirit/include/qi.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/spirit/include/phoenix.hpp>

namespace qi = boost::spirit::qi;

struct basic_value_t {
  uint8_t type;        
  std::vector<uint8_t> val;
};


BOOST_FUSION_ADAPT_STRUCT
(
 basic_value_t,
 (std::uint8_t, type)
 (std::vector<std::uint8_t>, val)
)

template <typename Iterator_T>
struct my_grammar :
qi::grammar<Iterator_T, std::vector<basic_value_t>() >
{
  my_grammar();

  qi::rule<Iterator_T, std::vector<basic_value_t>() > start;
  qi::rule<Iterator_T, basic_value_t(), qi::locals<size_t> > ptuple;
};

template <typename Iterator_T>
my_grammar<Iterator_T>::
my_grammar() : my_grammar<Iterator_T>::base_type(start), start(), ptuple() {
  start = (*ptuple);

  ptuple
    %= (qi::byte_ >>
       qi::omit[qi::byte_[qi::_a = qi::_1]] >>
       qi::repeat(qi::_a)[qi::byte_])
    ;
}

int main()
{
    std::vector<std::uint8_t> test = {1,3,1,2,3};
    my_grammar<std::vector<std::uint8_t>::const_iterator> grammar;

    std::vector<std::uint8_t>::const_iterator iter = test.begin(), end = test.end();

    std::vector<basic_value_t> parsed_value_vector;

    bool result = qi::parse(iter,end,grammar,parsed_value_vector);

    if(result && iter==end)
    {
        std::cout << "Success: Type=" << static_cast<int>(parsed_value_vector[0].type) << "; Vals= ";
        for(int num : parsed_value_vector[0].val)
            std::cout << num << ".";
        std::cout << std::endl;
    }
    else
    {
        std::cout << "Failure." << std::endl;
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top