Using boost 1.61, on both clang 3.8.0, and GCC 5.4, I get errors when compiling the following code:
#include <string>
#include <boost/spirit/home/x3.hpp>
#include <boost/fusion/adapted.hpp>
#include <tuple>
#include <vector>
#include <cassert>
void do_test(std::string input)
{
namespace x3 = boost::spirit::x3;
using x3::char_;
using x3::lit;
using x3::alpha;
auto const word = +(alpha - ' ');
auto first = begin(input);
auto last = end(input);
//this works
{
auto const& g = word;
std::string out;
x3::parse(first, last, g, out);
}
{
auto const& g = (word % ',');
std::vector<std::string> out;
x3::parse(first, last, g, out);
}
{
auto const& g = lit('/') >> (word % ',');
std::vector<std::string> out;
x3::parse(first, last, g, out);
}
{
auto const& g = -(word % ',');
std::vector<std::string> out;
x3::parse(first, last, g, out);
}
{
auto const& g = -(lit('/') >> (word % ','));
std::vector<std::string> out;
x3::parse(first, last, g, out);
}
{
auto const& g = -(lit('/') >> (word % ',') >> -lit('/'));
std::vector<std::string> out;
x3::parse(first, last, g, out);
}
{
auto const& g = word >> lit(':') >> word;
std::tuple<std::string, std::string> out;
x3::parse(first, last, g, out);
}
{
auto const& g = word >> lit(':') >> -(word % ',');
std::tuple<std::string, std::vector<std::string>> out;
x3::parse(first, last, g, out);
}
//but this fails.
{
auto const& g = word >> lit(':') >> -(lit('/') >> (word % ',') >> -lit('/'));
std::tuple<std::string, std::vector<std::string>> out;
x3::parse(first, last, g, out);
}
{
auto const& g = word >> lit(':') >> -((word % ',') >> -lit('/'));
std::tuple<std::string, std::vector<std::string>> out;
x3::parse(first, last, g, out);
}
}
with the following error message:
FAILED: /usr/bin/x86_64-linux-gnu-g++ -I../ext/boost-spirit/include -g -ggdb3 -fPIC -std=gnu++14 -MD -MT src/rtsp-header-parse/CMakeFiles/rtsp-header-parse.dir/rtsp-header-parse/test.cpp.o -MF src/rtsp-header-parse/CMakeFiles/rtsp-header-parse.dir/rtsp-header-parse/test.cpp.o.d -o src/rtsp-header-parse/CMakeFiles/rtsp-header-parse.dir/rtsp-header-parse/test.cpp.o -c ../src/rtsp-header-parse/rtsp-header-parse/test.cpp
In file included from ../ext/boost-spirit/include/boost/spirit/home/x3/auxiliary/any_parser.hpp:15:0,
from ../ext/boost-spirit/include/boost/spirit/home/x3/auxiliary.hpp:11,
from ../ext/boost-spirit/include/boost/spirit/home/x3.hpp:14,
from ../src/rtsp-header-parse/rtsp-header-parse/test.cpp:2:
../ext/boost-spirit/include/boost/spirit/home/x3/support/traits/container_traits.hpp: In instantiation of ‘struct boost::spirit::x3::traits::container_value<boost::fusion::iterator_range<boost::fusion::std_tuple_iterator<std::tuple<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >, 1>, boost::fusion::std_tuple_iterator<std::tuple<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >, 2> >, void>’:
../ext/boost-spirit/include/boost/spirit/home/x3/core/detail/parse_into_container.hpp:227:12: required from ‘struct boost::spirit::x3::detail::parser_attr_is_substitute_for_container_value<boost::spirit::x3::plus<boost::spirit::x3::difference<boost::spirit::x3::char_class<boost::spirit::char_encoding::standard, boost::spirit::x3::alpha_tag>, boost::spirit::x3::literal_char<boost::spirit::char_encoding::standard, boost::spirit::x3::unused_type> > >, boost::fusion::iterator_range<boost::fusion::std_tuple_iterator<std::tuple<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >, 1>, boost::fusion::std_tuple_iterator<std::tuple<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >, 2> >, boost::spirit::x3::unused_type>’
../ext/boost-spirit/include/boost/mpl/aux_/nested_type_wknd.hpp:26:31: required from ‘struct boost::mpl::aux::nested_type_wknd<boost::spirit::x3::detail::parser_attr_is_substitute_for_container_value<boost::spirit::x3::plus<boost::spirit::x3::difference<boost::spirit::x3::char_class<boost::spirit::char_encoding::standard, boost::spirit::x3::alpha_tag>, boost::spirit::x3::literal_char<boost::spirit::char_encoding::standard, boost::spirit::x3::unused_type> > >, boost::fusion::iterator_range<boost::fusion::std_tuple_iterator<std::tuple<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >, 1>, boost::fusion::std_tuple_iterator<std::tuple<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >, 2> >, boost::spirit::x3::unused_type> >’
../ext/boost-spirit/include/boost/mpl/not.hpp:39:8: required from ‘struct boost::mpl::not_<boost::spirit::x3::detail::parser_attr_is_substitute_for_container_value<boost::spirit::x3::plus<boost::spirit::x3::difference<boost::spirit::x3::char_class<boost::spirit::char_encoding::standard, boost::spirit::x3::alpha_tag>, boost::spirit::x3::literal_char<boost::spirit::char_encoding::standard, boost::spirit::x3::unused_type> > >, boost::fusion::iterator_range<boost::fusion::std_tuple_iterator<std::tuple<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >, 1>, boost::fusion::std_tuple_iterator<std::tuple<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >, 2> >, boost::spirit::x3::unused_type> >’
../ext/boost-spirit/include/boost/mpl/aux_/nested_type_wknd.hpp:26:31: required from ‘struct boost::mpl::aux::nested_type_wknd<boost::mpl::not_<boost::spirit::x3::detail::parser_attr_is_substitute_for_container_value<boost::spirit::x3::plus<boost::spirit::x3::difference<boost::spirit::x3::char_class<boost::spirit::char_encoding::standard, boost::spirit::x3::alpha_tag>, boost::spirit::x3::literal_char<boost::spirit::char_encoding::standard, boost::spirit::x3::unused_type> > >, boost::fusion::iterator_range<boost::fusion::std_tuple_iterator<std::tuple<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >, 1>, boost::fusion::std_tuple_iterator<std::tuple<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >, 2> >, boost::spirit::x3::unused_type> > >’
../ext/boost-spirit/include/boost/mpl/aux_/preprocessed/gcc/or.hpp:23:8: required from ‘struct boost::mpl::aux::or_impl<false, boost::mpl::not_<boost::spirit::x3::detail::parser_attr_is_substitute_for_container_value<boost::spirit::x3::plus<boost::spirit::x3::difference<boost::spirit::x3::char_class<boost::spirit::char_encoding::standard, boost::spirit::x3::alpha_tag>, boost::spirit::x3::literal_char<boost::spirit::char_encoding::standard, boost::spirit::x3::unused_type> > >, boost::fusion::iterator_range<boost::fusion::std_tuple_iterator<std::tuple<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >, 1>, boost::fusion::std_tuple_iterator<std::tuple<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >, 2> >, boost::spirit::x3::unused_type> >, mpl_::bool_<false>, mpl_::bool_<false>, mpl_::bool_<false> >’
../ext/boost-spirit/include/boost/mpl/aux_/preprocessed/gcc/or.hpp:48:8: [ skipping 7 instantiation contexts, use -ftemplate-backtrace-limit=0 to disable ]
../ext/boost-spirit/include/boost/spirit/home/x3/core/proxy.hpp:42:73: required from ‘bool boost::spirit::x3::proxy<Subject, Derived>::parse(Iterator&, const Iterator&, const Context&, RuleContext&, Attribute&) const [with Iterator = __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char> >; Context = boost::spirit::x3::unused_type; RuleContext = const boost::spirit::x3::unused_type; Attribute = boost::fusion::iterator_range<boost::fusion::std_tuple_iterator<std::tuple<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >, 1>, boost::fusion::std_tuple_iterator<std::tuple<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >, 2> >; Subject = boost::spirit::x3::sequence<boost::spirit::x3::list<boost::spirit::x3::plus<boost::spirit::x3::difference<boost::spirit::x3::char_class<boost::spirit::char_encoding::standard, boost::spirit::x3::alpha_tag>, boost::spirit::x3::literal_char<boost::spirit::char_encoding::standard, boost::spirit::x3::unused_type> > >, boost::spirit::x3::literal_char<boost::spirit::char_encoding::standard, boost::spirit::x3::unused_type> >, boost::spirit::x3::optional<boost::spirit::x3::literal_char<boost::spirit::char_encoding::standard, boost::spirit::x3::unused_type> > >; Derived = boost::spirit::x3::optional<boost::spirit::x3::sequence<boost::spirit::x3::list<boost::spirit::x3::plus<boost::spirit::x3::difference<boost::spirit::x3::char_class<boost::spirit::char_encoding::standard, boost::spirit::x3::alpha_tag>, boost::spirit::x3::literal_char<boost::spirit::char_encoding::standard, boost::spirit::x3::unused_type> > >, boost::spirit::x3::literal_char<boost::spirit::char_encoding::standard, boost::spirit::x3::unused_type> >, boost::spirit::x3::optional<boost::spirit::x3::literal_char<boost::spirit::char_encoding::standard, boost::spirit::x3::unused_type> > > >]’
../ext/boost-spirit/include/boost/spirit/home/x3/operator/detail/sequence.hpp:312:13: required from ‘bool boost::spirit::x3::detail::parse_sequence(const Parser&, Iterator&, const Iterator&, const Context&, RContext&, Attribute&, boost::spirit::x3::traits::tuple_attribute) [with Parser = boost::spirit::x3::sequence<boost::spirit::x3::sequence<boost::spirit::x3::plus<boost::spirit::x3::difference<boost::spirit::x3::char_class<boost::spirit::char_encoding::standard, boost::spirit::x3::alpha_tag>, boost::spirit::x3::literal_char<boost::spirit::char_encoding::standard, boost::spirit::x3::unused_type> > >, boost::spirit::x3::literal_char<boost::spirit::char_encoding::standard, boost::spirit::x3::unused_type> >, boost::spirit::x3::optional<boost::spirit::x3::sequence<boost::spirit::x3::list<boost::spirit::x3::plus<boost::spirit::x3::difference<boost::spirit::x3::char_class<boost::spirit::char_encoding::standard, boost::spirit::x3::alpha_tag>, boost::spirit::x3::literal_char<boost::spirit::char_encoding::standard, boost::spirit::x3::unused_type> > >, boost::spirit::x3::literal_char<boost::spirit::char_encoding::standard, boost::spirit::x3::unused_type> >, boost::spirit::x3::optional<boost::spirit::x3::literal_char<boost::spirit::char_encoding::standard, boost::spirit::x3::unused_type> > > > >; Iterator = __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char> >; Context = boost::spirit::x3::unused_type; RContext = const boost::spirit::x3::unused_type; Attribute = std::tuple<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >]’
../ext/boost-spirit/include/boost/spirit/home/x3/operator/sequence.hpp:44:42: required from ‘bool boost::spirit::x3::sequence<Left, Right>::parse(Iterator&, const Iterator&, const Context&, RContext&, Attribute&) const [with Iterator = __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char> >; Context = boost::spirit::x3::unused_type; RContext = const boost::spirit::x3::unused_type; Attribute = std::tuple<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >; Left = boost::spirit::x3::sequence<boost::spirit::x3::plus<boost::spirit::x3::difference<boost::spirit::x3::char_class<boost::spirit::char_encoding::standard, boost::spirit::x3::alpha_tag>, boost::spirit::x3::literal_char<boost::spirit::char_encoding::standard, boost::spirit::x3::unused_type> > >, boost::spirit::x3::literal_char<boost::spirit::char_encoding::standard, boost::spirit::x3::unused_type> >; Right = boost::spirit::x3::optional<boost::spirit::x3::sequence<boost::spirit::x3::list<boost::spirit::x3::plus<boost::spirit::x3::difference<boost::spirit::x3::char_class<boost::spirit::char_encoding::standard, boost::spirit::x3::alpha_tag>, boost::spirit::x3::literal_char<boost::spirit::char_encoding::standard, boost::spirit::x3::unused_type> > >, boost::spirit::x3::literal_char<boost::spirit::char_encoding::standard, boost::spirit::x3::unused_type> >, boost::spirit::x3::optional<boost::spirit::x3::literal_char<boost::spirit::char_encoding::standard, boost::spirit::x3::unused_type> > > >]’
../ext/boost-spirit/include/boost/spirit/home/x3/core/parse.hpp:35:68: required from ‘bool boost::spirit::x3::parse_main(Iterator&, Iterator, const Parser&, Attribute&) [with Iterator = __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char> >; Parser = boost::spirit::x3::sequence<boost::spirit::x3::sequence<boost::spirit::x3::plus<boost::spirit::x3::difference<boost::spirit::x3::char_class<boost::spirit::char_encoding::standard, boost::spirit::x3::alpha_tag>, boost::spirit::x3::literal_char<boost::spirit::char_encoding::standard, boost::spirit::x3::unused_type> > >, boost::spirit::x3::literal_char<boost::spirit::char_encoding::standard, boost::spirit::x3::unused_type> >, boost::spirit::x3::optional<boost::spirit::x3::sequence<boost::spirit::x3::list<boost::spirit::x3::plus<boost::spirit::x3::difference<boost::spirit::x3::char_class<boost::spirit::char_encoding::standard, boost::spirit::x3::alpha_tag>, boost::spirit::x3::literal_char<boost::spirit::char_encoding::standard, boost::spirit::x3::unused_type> > >, boost::spirit::x3::literal_char<boost::spirit::char_encoding::standard, boost::spirit::x3::unused_type> >, boost::spirit::x3::optional<boost::spirit::x3::literal_char<boost::spirit::char_encoding::standard, boost::spirit::x3::unused_type> > > > >; Attribute = std::tuple<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >]’
../ext/boost-spirit/include/boost/spirit/home/x3/core/parse.hpp:47:26: required from ‘bool boost::spirit::x3::parse(Iterator&, Iterator, const Parser&, Attribute&) [with Iterator = __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char> >; Parser = boost::spirit::x3::sequence<boost::spirit::x3::sequence<boost::spirit::x3::plus<boost::spirit::x3::difference<boost::spirit::x3::char_class<boost::spirit::char_encoding::standard, boost::spirit::x3::alpha_tag>, boost::spirit::x3::literal_char<boost::spirit::char_encoding::standard, boost::spirit::x3::unused_type> > >, boost::spirit::x3::literal_char<boost::spirit::char_encoding::standard, boost::spirit::x3::unused_type> >, boost::spirit::x3::optional<boost::spirit::x3::sequence<boost::spirit::x3::list<boost::spirit::x3::plus<boost::spirit::x3::difference<boost::spirit::x3::char_class<boost::spirit::char_encoding::standard, boost::spirit::x3::alpha_tag>, boost::spirit::x3::literal_char<boost::spirit::char_encoding::standard, boost::spirit::x3::unused_type> > >, boost::spirit::x3::literal_char<boost::spirit::char_encoding::standard, boost::spirit::x3::unused_type> >, boost::spirit::x3::optional<boost::spirit::x3::literal_char<boost::spirit::char_encoding::standard, boost::spirit::x3::unused_type> > > > >; Attribute = std::tuple<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >]’
../src/rtsp-header-parse/rtsp-header-parse/test.cpp:72:38: required from here
../ext/boost-spirit/include/boost/spirit/home/x3/support/traits/container_traits.hpp:76:12: error: no type named ‘value_type’ in ‘struct boost::fusion::iterator_range<boost::fusion::std_tuple_iterator<std::tuple<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >, 1>, boost::fusion::std_tuple_iterator<std::tuple<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >, 2> >’
struct container_value
^
In file included from ../ext/boost-spirit/include/boost/spirit/home/x3/directive/expect.hpp:12:0,
from ../ext/boost-spirit/include/boost/spirit/home/x3/auxiliary/guard.hpp:11,
from ../ext/boost-spirit/include/boost/spirit/home/x3/auxiliary.hpp:13,
from ../ext/boost-spirit/include/boost/spirit/home/x3.hpp:14,
from ../src/rtsp-header-parse/rtsp-header-parse/test.cpp:2:
...
I'm curious as to why the combination of the %
operator with the inclusion of optional with an internal sequenced section causes a compilation to fail. ie: why does -(word % ',')
work without issue, but -((word % ',') >> lit('/'))
fail to parse into a subexpression? At the same time, why does it work when removing the prefix word and parsing directly into a std::vector<std::string>
?
I've also tried to parse into a boost::mpl::vector<std::string, std::vector<std::string>>
and get the same errors.