I am trying to have an x3 parser work with std::variant
instead of boost::variant
, without success.
I followed the post on this subject: transitioning boost spirit parser from boost::variant to std::variant but the required boiler plate to have it work does not seem to work in my case. The (simplified) error message states:
std::variant<...> has no member named apply_visitor
which I confess, but this boiler plates being so an UFO to me, I won't be able to fix it.
Here is a minimal test code to reproduce my issue, available on coliru:
#include <iostream>
#include <variant>
#define BOOST_SPIRIT_X3_DEBUG
#include "boost/spirit/home/x3.hpp"
#include "boost/spirit/include/support_istream_iterator.hpp"
// boiler plate provided in the original post
namespace boost::spirit::x3::traits {
template<typename... T>
struct is_variant<std::variant<T...> >
: mpl::true_ {};
template <typename Attribute, typename... T>
struct variant_has_substitute_impl<std::variant<T...>, Attribute>
{
typedef std::variant<T...> variant_type;
typedef typename mpl::transform<
mpl::list<T...>
, unwrap_recursive<mpl::_1>
>::type types;
typedef typename mpl::end<types>::type end;
typedef typename mpl::find<types, Attribute>::type iter_1;
typedef typename
mpl::eval_if<
is_same<iter_1, end>,
mpl::find_if<types, traits::is_substitute<mpl::_1, Attribute>>,
mpl::identity<iter_1>
>::type
iter;
typedef mpl::not_<is_same<iter, end>> type;
};
template <typename Attribute, typename... T>
struct variant_find_substitute<std::variant<T...>, Attribute>
{
typedef std::variant<T...> variant_type;
typedef typename mpl::transform<
mpl::list<T...>
, unwrap_recursive<mpl::_1>
>::type types;
typedef typename mpl::end<types>::type end;
typedef typename mpl::find<types, Attribute>::type iter_1;
typedef typename
mpl::eval_if<
is_same<iter_1, end>,
mpl::find_if<types, traits::is_substitute<mpl::_1, Attribute> >,
mpl::identity<iter_1>
>::type
iter;
typedef typename
mpl::eval_if<
is_same<iter, end>,
mpl::identity<Attribute>,
mpl::deref<iter>
>::type
type;
};
template <typename... T>
struct variant_find_substitute<std::variant<T...>, std::variant<T...> >
: mpl::identity<std::variant<T...> > {};
}
namespace x3 = boost::spirit::x3;
typedef std::variant<unsigned int, std::string> type_t;
static_assert(x3::traits::is_variant<type_t>{}, "");
static std::ostream & operator<<(std::ostream& o, type_t const & v)
{
if (std::holds_alternative<unsigned int>(v))
o << std::get<unsigned int>(v) << "\n";
else
o << std::get<std::string>(v) << "\n";
return o;
}
int main(void)
{
static_assert(x3::traits::is_variant<type_t>::value);
auto const parser
= x3::rule<struct parser_tag, type_t >{ "parser" }
= ('{' >> (x3::uint_ | x3::string("Hello")) >> '}');
type_t var;
std::string input("{12}");
bool v = x3::phrase_parse(input.begin(), input.end(), parser ,x3::space,var);
std::cout << "parsing : " << (v ? "OK" : "KO") << "\n";
std::cout << "var = " << var << "\n";
return 0;
}